Given a sequence which contains only various amounts of the numbers 1, 2, 3, and 4 (examples: 13244, 4442, etc), I want to count all its permutations such that no two adjacent numbers are the same. I believe it is O(N! * N) and want to know if there is a better one out there. Anyone have any ideas?
class Ideone
{
static int permutationCount++;
public static void main(String[] args) {
String str = "442213";
permutation("", str);
System.out.println(permutationCount);
}
private static void permutation(String prefix, String str) {
int n = str.length();
if (n == 0){
boolean bad = false;
//Check whether there are repeating adjacent characters
for(int i = 0; i < prefix.length()-1; i++){
if(prefix.charAt(i)==prefix.charAt(i+1))
bad = true;
}
if(!bad){
permutationCount++;
}
}
else {
//Recurse through permutations
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
}
}
}
I understand your question like this: Given a string containing only numbers 1,2,3,4 - how many permutations of these characters exist that when you put them into string again there won't be any same adjecent numbers.
I would suggest this approach:
L - length of your string
n1 - how many times is 1 repeated, n2 - how many times is 2 repeated etc.
P - number of all possible permutations
P = L! / (n1!*n2!*n3!*n4!)
C - number of all solutions fitting your constraint
C = P - start with all permutations
substract all permutations which have 11 in it (just take 11 as one number)
C = C - (L - 1)! / ((n1 - 1)! * n2! * n3! * n4!)
... do the same for 22 ...
add all permutations which have both 11 and 22 in it (because we have substracted them twice, so you need to add them)
C = C + (L - 2)! / ((n1 - 1)! * (n2 - 1)! * n3! * n4!)
... repeat previous steps for 33 and 44 ...
If you just want to calculate how many permutations match your constraint, it is not required to spell each of them out.
If I get your question right, your input string has 4 distinct input characters 1,2,3,4 and you want to know how many permutations of this are possible?
Then you should use some maths, namely n! / (n-r)!, where n is the number of elements to choose from (4 in this case) and r is the number of positions you want to fill (also 4).
Your example would have 4! / (4-4)! = 24 permutations possible:
{1,2,3,4} {1,2,4,3} {1,3,2,4} {1,3,4,2} {1,4,2,3} {1,4,3,2}
{2,1,3,4} {2,1,4,3} {2,3,1,4} {2,3,4,1} {2,4,1,3} {2,4,3,1}
{3,1,2,4} {3,1,4,2} {3,2,1,4} {3,2,4,1} {3,4,1,2} {3,4,2,1}
{4,1,2,3} {4,1,3,2} {4,2,1,3} {4,2,3,1} {4,3,1,2} {4,3,2,1}
In a nutshell, for length n with n distinct values the count of permutations is n!:
1 -> 1
2 -> 2
3 -> 6
4 -> 24
5 -> 120
...
Edit: After your edits and comments it is clear that I misunderstood the question.
If you just want to check to see if there are no matching adjacent numbers, then you can use a simple loop. This will be O(n) complexity.
public static void main(String[] args) {
String str = "442213";
System.out.println(permutation(str));
}
public static int permutation(String str) {
int permutationCount = 0;
if (str.length() > 1) {
for (int i = 0; i < str.length() - 1; i++) {
if (str.charAt(i) != str.charAt(i + 1)) {
permutationCount++;
}
}
}
return permutationCount;
}
If you wanted to stick with recursion, you could do something like this:
public static void main(String[] args) {
String str = "442213";
System.out.println(permutation(str, 0));
}
public static int permutation(String str, int currentIndex) {
int permutationCount = 0;
if (str == null || currentIndex + 1 >= str.length()) {
return permutationCount;
}
if (str.charAt(currentIndex) != str.charAt(currentIndex + 1)) {
permutationCount = 1;
}
return permutationCount + permutation(str, currentIndex + 1);
}
Related
public static int reverse(int n) {
int result = 0;
while (n > 0) {
result = result * 10 + n % 10;
n = n / 10;
}
return result;
}
I'm trying to reverse the digits of integer. Instead of doing the codes like what I have done, is there any other way to do it? Can i reverse it using java stream?
Another way would be
int digits = 12345;
StringBuilder buf = new StringBuilder(String.valueOf(digits));
System.out.println(buf.reverse());
System.out.println(Integer.valueOf(buf.toString()));
OK, here's a fun implementation with IntStream:
public static int reverse (int n) {
return IntStream.iterate (n, i -> i/10) // produces a infinite IntStream of n, n/10,
// n/100, ...
.limit(10) // 10 elements are sufficient, since int has <= 10 digits
.filter (i -> i > 0) // remove any trailing 0 elements
.map(i -> i % 10) // produce an IntStream of the digits in reversed
// order
.reduce (0, (r,i) -> r*10 + i); // reduce the reversed digits back
// to an int
}
For example, for the input 123456789, it will first generate the infinite IntStream:
123456789,12345678,1234567,123456,12345,1234,123,12,1,0,0,...
After limiting to 10 elements and removing the 0s, we are left with:
123456789,12345678,1234567,123456,12345,1234,123,12,1
After mapping each element to its last digit, we get:
9,8,7,6,5,4,3,2,1
Now we just have to reduce the IntStream in a manner similar to what you did in your question - add each element to the intermediate result multiplied by 10:
((((0 * 10 + 9) * 10 + 8) * 10 + 7) * 10 ....) * 10 + 1
Note that if the input number has 10 digits and the last digit > 1, the reversed result will overflow.
It also doesn't support negative input.
One more stream and Math fun implementation.
public static long reverse(int n) {
return Stream.iterate(
Map.entry(0, n % 10),
entry -> Math.pow(10, entry.getKey()) <= n,
entry -> Map.entry(entry.getKey() + 1,
(int) (n % (int) Math.pow(10, entry.getKey() + 2) / Math.pow(10, entry.getKey() + 1))))
.map(Map.Entry::getValue)
.map(Integer::longValue)
.reduce(0L, (r, i) -> r * 10 + i);
}
You should return long in your method, anyway. But StringBuilder is the best here.
A Stream solution which returns for a given number the reversed String:
int n = 10101010;
String reveresed = String.valueOf(n)
.chars()
.mapToObj(Character::getNumericValue)
.reduce("", (l, r) -> r + l, (l, r) -> l + r);
System.out.println(reveresed); // 01010101
If we convert the reversed String to an Integer and print it we will lose the leading zero:
System.out.println(Integer.valueOf(reveresed).toString()); // 1010101
Along with the other answers, you can try this implementation as well.
public class MyStreamReverser {
public static void main(String[] args) {
streamApiReverser(-9008);
// other outputs to test:
// streamApiReverser(20000090);
// streamApiReverser(-04);
// streamApiReverser(39-02);
}
private static void streamApiReverser(int n) {
// produce an array of strings each having one digit
String[] stringArray = String.valueOf(n).split("\\B");
Stream<String> stringStream = Arrays.stream(stringArray);
stringStream.collect(Collectors.toCollection(LinkedList::new))
.descendingIterator()
.forEachRemaining(System.out::println);
}
}
Output:
8
0
0
-9
Note - Does not play well with leading zeros. 09 doesn't work (since those are treated as octals), works with trailing zeros, should be fine with negatives (but further testing needed).
An easy way to reverse an integer is to parse it into a string, reverse it, and parse it back into a integer.
public static int reverse(int num) {
StringBuffer stringBuffer = new StringBuffer(String.valueOf(num););
stringBuffer.reverse();
return Integer.parseInt(stringBuffer.toString());
}
the quickest answer will be :
public int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x%10;
x /= 10;
if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
rev = rev*10+pop;
}
return rev;
}
I am working with gray code and I got almost everything, but when the code run, like 1-bit or 2-bit it only prints out 0000 rather than 00 01 11 10.
class GrayCode {
static void genGC(int n){
if(n == 0){
System.out.println(n);
}
else{
genGC(n-1);
genGC(n-1);
}
}
public static void main(String[] args) {
int a = 2;
genGC(a);
}
}
Your problem is that the Gray codes of the required bit length arent just the concatenation of the Grey codes of bit length one less. It's more complicated than that.
This seems to work - although there is an unnecessary amount of list copying - I may try to fix that in a later version.
/**
* Prefix every element of the list with the string.
*
* #param list - The list to prefix.
* #param prefix - The string to prefix each element.
* #return - A new prefixed list.
*/
private List<String> prefix(List<String> list, String prefix) {
List<String> prefixed = new ArrayList<>(list.size());
for (String s : list) {
prefixed.add(prefix + s);
}
return prefixed;
}
/**
* Reflect(reverse) a list.
*
* #param list - The list to reverse.
* #return The reversed list.
*/
private List<String> reflected(List<String> list) {
List<String> reflected = new ArrayList<>(list.size());
// use an ArrayList so I can reverse iterate.
for (ListIterator<String> backwards = new ArrayList<>(list).listIterator(list.size()); backwards.hasPrevious();) {
reflected.add(backwards.previous());
}
return reflected;
}
// Grey codes of one-bit numbers is (0,1).
private static final List<String> OneBit = Arrays.asList("0", "1");
public List<String> greyCodes(int bits) {
if (bits <= 1) {
return OneBit;
} else {
List<String> smaller = greyCodes(bits - 1);
// Prefix the current list with "0"
List<String> grey = prefix(smaller, "0");
// and a reflected version of that list with "1"
grey.addAll(prefix(reflected(smaller), "1"));
return grey;
}
}
The actual recursion to generate the kth Gray code having n bits is ('||' means concatenation):
G (n, k) = 1 || G (n - 1, 2n - k - 1) for k ≥ 2n - 1
G (n, k) = 0 || G (n - 1, k) for k n - 1
Using stopping conditions G (1, 0) = 0 and G (1, 1) = 1 and having 0 ≤ k ≤ 2k - 1
Note the subtraction in (2). It corresponds to the fact that the first half of the sequence of the last 4 digits is a mirror image of the second half. This is why Gray codes are sometimes called Reflected Binary Code (RBC).
If Lisp/Scheme/etc. is your thing, you could generate bit arrays with Gray codes using:
(defun gray (n k)
"Returns the kth Gray code of an n-bit sequence. Output is in the form of a bit array."
(assert (< k (expt 2 n)) (n) "k cannot be higher than ~A~%" (1- (expt 2 n)))
(cond
((= n 1)
(if (zerop k) #*0 #*1))
((>= k (expt 2 (1- n)))
(concatenate 'bit-vector #*1 (gray (1- n) (- (expt 2 n) k 1))))
(t
(concatenate 'bit-vector #*0 (gray (1- n) k)))))
NB. cond above works like switch/case in Java. The function above is a straightforward implementation of the recursive formula above.
If Lisp is not your thing and if recursion is not an absolute requirement for your program, you can amend your code by implementing the formula:
gray = num ^ (num >> 1)
Cheers,
Paulo
Here is a fairly simple Java recursive program that takes a positive integer n and produces n-bit Gray codes:
public static String swap(String s, String r, int i)
{
i = i-1;
String t = s.substring(0,i) + r + s.substring(i+1);
return t;
}
swap takes a string and changes its i-1 character with another string that contains only one character.
public static void beckett(int n, String s)
{
if (n == 0) return;
beckett(n-1, s);
System.out.println(swap(s, "1", n)); s = swap(s, "1", n);
beckett(n-1, s);
}
beckett (in reference to one of Beckett's plays named Quad) produces the Gray codes.
public static void grayCodes(int n)
{
String s = "";
for (int i = 0; i < n; i++)
s += "0";
System.out.println(s);
beckett(n, s);
}
grayCodes makes working with beckett easier (merely reduces the number of inputs).
You can test the above methods with:
public static void main(String[] args)
{
int n = Integer.parseInt(args[0]);
grayCodes(n);
}
For the sample input 3 it gives the following output:
000
100
010
110
001
101
011
111
Hope this helps.
I am trying to solve this question as the preparation for a programming interview:
A frog only moves forward, but it can move in steps 1 inch long or in jumps 2 inches long. A frog can cover the same distance using different combinations of steps and jumps.
Write a function that calculates the number of different combinations a frog can use to cover a given distance.
For example, a distance of 3 inches can be covered in three ways: step-step-step, step-jump, and jump-step.
I think there is a quite simple solution to this, but I just can't seem to find it. I would like to use recursion, but I can't see how. Here is what I have so far:
public class Frog {
static int combinations = 0;
static int step = 1;
static int jump = 2;
static int[] arr = {step, jump};
public static int numberOfWays(int n) {
for (int i = 0; i < arr.length; i++) {
int sum = 0;
sum += arr[i];
System.out.println("SUM outer loop: " + sum + " : " + arr[i]);
while (sum != 3) {
for (int j = 0; j < arr.length; j++) {
if (sum + arr[j] <= 3) {
sum += arr[j];
System.out.println("SUM inner loop: " + sum + " : " + arr[j]);
if (sum == 3) {
combinations++;
System.out.println("Combinations " + combinations);
}
}
}
}
}
return combinations;
}
public static void main(String[] args) {
System.out.println(numberOfWays(3));
}
}
It doesn't find all combinations, and I think the code is quite bad. Anyone have a good solution to this question?
Think you have an oracle that knows how to solve the problem for "smaller problems", you just need to feed it with smaller problems. This is the recursive method.
In your case, you solve foo(n), by splitting the possible moves the frog can do in the last step, and summing them):
foo(n) = foo(n-1) + foo(n-2)
^ ^
1 step 2 steps
In addition, you need a stop clause of foo(0) = 1, foo(1)=1 (one way to move 0 or 1 inches).
Is this recursive formula looks familiar? Can you solve it better than the naive recursive solution?
Spoiler:
Fibonacci Sequence
Here's a simple pseudo-code implementation that should work:
var results = []
function plan(previous, n){
if (n==0) {
results.push(previous)
} else if (n > 0){
plan(previous + ' step', n-1)
plan(previous + ' hop', n-2)
}
}
plan('', 5)
If you want to improve the efficiency of an algorithm like this you could look into using memoization
Here's a combinatoric way: think of n as 1 + 1 + 1 ... = n. Now bunch the 1's in pairs, gradually increasing the number of bunched 1's, summing the possibilities to arrange them.
For example, consider 5 as 1 1 1 1 1:
one bunch => (1) (1) (1) (11) => 4 choose 1 possibilities to arrange one 2 with three 1's
two bunches => (1) (11) (11) => 3 choose 2 possibilities to arrange two 2's with one 1
etc.
This seems directly related to Wikipedia's description of Fibonacci numbers' "Use in Mathematics," for example, in counting "the number of compositions of 1s and 2s that sum to a given total n" (http://en.wikipedia.org/wiki/Fibonacci_number).
This logic is working fine. (Recursion)
public static int numberOfWays(int n) {
if (n== 1) {
return 1; // step
} else if (n== 2) {
return 2; // (step + step) or jump
} else {
return numberOfWays(n- 1)
+ numberOfWays(n- 2);
}
}
The accepted answer fails performance test for larger sets. Here is a version with for loop that satisfies performance tests at testdome.
using System;
public class Frog
{
public static int NumberOfWays (int n)
{
int first = 0, second = 1;
for ( int i = 0; i<n; i++ )
{
int at = first;
first = second;
second = at + second;
}
return second;
}
public static void Main (String[] args)
{
Console.WriteLine (NumberOfWays (3));
}
}
C++ code works fine.
static int numberOfWays(int n)
{
if (n == 1) return 1;
else if (n == 2) return 2;
else
{
static std::unordered_map<int,int> m;
auto i = m.find(n);
if (i != m.end())
return i->second;
int x = numberOfWays(n - 1) + numberOfWays(n - 2);
m[n] = x;
return x;
}
}
I am stuck on the coin denomination problem.
I am trying to find the lowest number of coins used to make up $5.70 (or 570 cents). For example, if the coin array is {100,5,2,5,1} (100 x 10c coins, 5 x 20c, 2 x 50c, 5 x $1, and 1 x $2 coin), then the result should be {0,1,1,3,1}
At the moment the coin array will consist of the same denominations ( $2, $1, 50c, 20c, 10c)
public static int[] makeChange(int change, int[] coins) {
// while you have coins of that denomination left and the total
// remaining amount exceeds that denomination, take a coin of that
// denomination (i.e add it to your result array, subtract it from the
// number of available coins, and update the total remainder). –
for(int i= 0; i< coins.length; i++){
while (coins[i] > 0) {
if (coins[i] > 0 & change - 200 >= 0) {
coins[4] = coins[4]--;
change = change - 200;
} else
if (coins[i] > 0 & change - 100 >= 0) {
coins[3] = coins[3]--;
change = change - 100;
} else
if (coins[i] > 0 & change - 50 >= 0) {
coins[2] = coins[2]--;
change = change - 50;
} else
if (coins[i] > 0 & change - 20 >= 0) {
coins[1] = coins[1]--;
change = change - 20;
} else
if (coins[i] > 0 & change - 10 >= 0) {
coins[0] = coins[0]--;
change = change - 10;
}
}
}
return coins;
}
I am stuck on how to deduct the values from coins array and return it.
EDIT: New code
The brute force solution is to try up to the available number of coins of the highest denomination (stopping when you run out or the amount would become negative) and for each of these recurse on solving the remaining amount with a shorter list that excludes that denomination, and pick the minimum of these. If the base case is 1c the problem can always be solved, and the base case is return n otherwise it is n/d0 (d0 representing the lowest denomination), but care must be taken to return a large value when not evenly divisible so the optimization can pick a different branch. Memoization is possible, and parameterized by the remaining amount and the next denomination to try. So the memo table size would be is O(n*d), where n is the starting amount and d is the number of denominations.
So the problem can be solved in pseudo-polynomial time.
The wikipedia link is sparse on details on how to decide if a greedy algorithm such as yours will work. A better reference is linked in this CS StackExchange question. Essentially, if the coin system is canonical, a greedy algorithm will provide an optimal solution. So, is [1, 2, 5, 10, 20] canonical? (using 10s of cents for units, so that the sequence starts in 1)
According to this article, a 5-coin system is non-canonical if and only if it satisfies exactly one of the following conditions:
[1, c2, c3] is non-canonical (false for [1, 2, 5])
it cannot be written as [1, 2, c3, c3+1, 2*c3] (true for [1, 2, 5, 10, 20])
the greedyAnswerSize((k+1) * c4) > k+1 with k*c4 < c5 < (k+1) * c4; in this case, this would require a k*10 < 20 < (k+1)*10; there is no integer k in that range, so this is false for [1, 2, 5, 10, 20].
Therefore, since the greedy algorithm will not provide optimal answers (and even if it did, I doubt that it would work with limited coins), you should try dynamic programming or some enlightened backtracking:
import java.util.HashSet;
import java.util.PriorityQueue;
public class Main {
public static class Answer implements Comparable<Answer> {
public static final int coins[] = {1, 2, 5, 10, 20};
private int availableCoins[] = new int[coins.length];
private int totalAvailable;
private int totalRemaining;
private int coinsUsed;
public Answer(int availableCoins[], int totalRemaining) {
for (int i=0; i<coins.length; i++) {
this.availableCoins[i] = availableCoins[i];
totalAvailable += coins[i] * availableCoins[i];
}
this.totalRemaining = totalRemaining;
}
public boolean hasCoin(int coinIndex) {
return availableCoins[coinIndex] > 0;
}
public boolean isPossibleBest(Answer oldBest) {
boolean r = totalRemaining >= 0
&& totalAvailable >= totalRemaining
&& (oldBest == null || oldBest.coinsUsed > coinsUsed);
return r;
}
public boolean isAnswer() {
return totalRemaining == 0;
}
public Answer useCoin(int coinIndex) {
Answer a = new Answer(availableCoins, totalRemaining - coins[coinIndex]);
a.availableCoins[coinIndex]--;
a.totalAvailable = totalAvailable - coins[coinIndex];
a.coinsUsed = coinsUsed+1;
return a;
}
public int getCoinsUsed() {
return coinsUsed;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
for (int c : availableCoins) sb.append(c + ",");
sb.setCharAt(sb.length()-1, '}');
return sb.toString();
}
// try to be greedy first
#Override
public int compareTo(Answer a) {
int r = totalRemaining - a.totalRemaining;
return (r==0) ? coinsUsed - a.coinsUsed : r;
}
}
// returns an minimal set of coins to solve
public static int makeChange(int change, int[] availableCoins) {
PriorityQueue<Answer> queue = new PriorityQueue<Answer>();
queue.add(new Answer(availableCoins, change));
HashSet<String> known = new HashSet<String>();
Answer best = null;
int expansions = 0;
while ( ! queue.isEmpty()) {
Answer current = queue.remove();
expansions ++;
String s = current.toString();
if (current.isPossibleBest(best) && ! known.contains(s)) {
known.add(s);
if (current.isAnswer()) {
best = current;
} else {
for (int i=0; i<Answer.coins.length; i++) {
if (current.hasCoin(i)) {
queue.add(current.useCoin(i));
}
}
}
}
}
// debug
System.out.println("After " + expansions + " expansions");
return (best != null) ? best.getCoinsUsed() : -1;
}
public static void main(String[] args) {
for (int i=0; i<100; i++) {
System.out.println("Solving for " + i + ":"
+ makeChange(i, new int[]{100,5,2,5,1}));
}
}
}
You are in wrong direction. This program will not give you an optimal solution. To get optimal solution go with dynamic algorithms implemented and discussed here. Please visit these few links:
link 1
link 2
link 3
For example, I need to grab an unknown number, let's say 3, and find the binary (2^3) - 1 times, from 0 to 111 (0-7). Obviously, the number of digits I need depends on whatever number 'n' in 2^n.
So, if the number is 3, I would need the output to be:
000
001
010
011
100
101
111
Now obviously I can do this manually with a String.format("%03d", NumberInBinary) operation, but that's hardcoding it for 3 digits. I need to do the equivalent code with an unknown number of digits, how can I do that? (as in String.format("%0nd", yournumber) where n is the number of digits.)
if n = 4, NumberInBinary = 101;
String.format("%0"+n+"d", NumberInBinary);
with output
0101
Why not make use of the already built-in Integer.toBinaryString() and just manually add the zeros using a StringBuilder ?
public static void main(String[] args) {
int max = 5;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
String binary = Integer.toBinaryString(i);
if (binary.length() > max) {
break;
}
System.out.println( prefixWithZeros(binary, max) );
}
}
static String prefixWithZeros(String binary, int n) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n - binary.length(); i++) {
sb.append('0');
}
return sb.append(binary).toString();
}
You could use recursion:
public static void enumerate(String prefix, int remaining) {
if (remaining == 0) {
System.out.println(prefix);
} else {
enumerate(prefix + "0", remaining - 1);
enumerate(prefix + "1", remaining - 1);
}
}
and then call enumerate("", numberOfDigits);
faster, using StringBuffer:
public static void enumerate(StringBuffer prefix, int remaining) {
if (remaining == 0) {
System.out.println(prefix.toString());
} else {
enumerate(prefix.append('0'), remaining - 1);
prefix.deleteCharAt(prefix.length() - 1);
enumerate(prefix.append('1'), remaining - 1);
prefix.deleteCharAt(prefix.length() - 1);
}
}
and then call enumerate(new StringBuffer(), numberOfDigits);