Minimum Coin Change Print All Combinations - algorithm

Given an array of coin denominations coins and a total, find all possible combinations that result in the minimum number of coins summing to the total. In my solution I keep a running track of the minimum number of coins at table[i] that sum to i. I'm not sure exactly how this would be modified to store the actual coins that sum to i and make sure that both possibilities in this case are included. I've looked at other code on stack overflow, but I've only found code that will print any one of the optimal solutions.
Input: minimum_coins(10, [2,3,5,6,7,8])Output: [[5,5],[2,8]]
INT_MAX = 2 ** 63 - 1
def minimum_coins(total, coins)
table = Array.new(total + 1)
table[0] = 0
(1..total).to_a.each do |i|
table[i] = INT_MAX
end
(1..total).to_a.each do |i|
(0..coins.length-1).to_a.each do |j|
if coins[j] <= i
sub_res = table[i-coins[j]]
if sub_res != INT_MAX && sub_res + 1 < table[i]
table[i] = sub_res + 1
end
end
end
end
puts table.inspect
end
minimum_coins(10, [2,3,5,6,7,8])

let:
d[i] = minimum changes for i
So if d[i] == d[i - c] + 1, we can say if we take coin c to make exchange and we can still get a minimum coin changes for i.
Code:
def find(n, result, d, coins, changes, index):
if n == 0:
changes.append(result)
return
for i in range(index, len(coins)):
if n - coins[i] >= 0 and d[n] == d[n - coins[i]] + 1:
find(n - coins[i], result + [coins[i]], d, coins, changes, i)
def all_coin_changes(n, coins):
d = [n + 1] * (n + 1)
d[0] = 0
for i in range(1, n + 1):
for c in coins:
if i - c >= 0:
d[i] = min(d[i], d[i - c] + 1)
changes = []
find(n, [], d, coins, changes, 0)
return changes
print all_coin_changes(10, [2, 3, 5, 6, 7, 8])
# [[2, 8], [3, 7], [5, 5]]
print all_coin_changes(100, [2, 3, 5, 6, 7, 8])
# [[5, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8]]
If you still have some questions, please don't hesitate to leave a comment here.

Let's table entries contain pairs (BestCount, LastCoinList).
If sub_res + 1 < table[i].BestCount then
replace BestCount with sub_res + 1 and make LastCoinList containing coins[j] value
If sub_res + 1 = table[i].BestCount then
just add coins[j] value to LastCoinList
So in the end table[10] will contain BestValue = 2 and LastCoinList = (5,7,8)
Now recursively unroll from table[10] entry to table[10-5], to table[10-7], to table[10-8], that contain 5,3 and 2 respectively, then all recursion branches stop at the 0th entry.

I made an iterative program that can calculate the minimum number of coins required (US dollars) to get a given number of cents. It's iterative, but hope it helps!
import java.util.*;
public class CoinProblem
{
public static void main(String[] args)
{
System.out.println("----------------------------COIN PROBLEM--------------------------");
System.out.println("Denominations: \nCent - 1\nNickel - 5\nDime - 10\nQuarter - 25");
Map<Integer, Integer> map = new HashMap<Integer, Integer> ();
System.out.println("\nENTER TARGET NUMBER (CENTS): ");
Scanner sc = new Scanner(System.in);
int target = Integer.parseInt(sc.next());
int count = numCoins(target, map);
System.out.println("\nMINIMUM NUMBER OF COINS REQUIRED: " + count);
System.out.println( map.get(1) + " CENTS");
System.out.println( map.get(5) + " NICKELS");
System.out.println( map.get(10) + " DIMES");
System.out.println( map.get(25) + " QUARTERS");
System.out.println("------------------------------------------------------------------");
}
public static int numCoins(int target, Map<Integer, Integer> map)
{
int cent = 1;
int nickel = 5;
int dime = 10;
int quarter = 25;
map.put(cent, 0);
map.put(nickel, 0);
map.put(dime, 0);
map.put(quarter, 0);
int count = 0;
if (target >= 25)
{
if (target % 25 == 0)
{
count += target/25;
map.put(quarter, count);
return count;
}
else
{
count += target/25;
map.put(quarter, count);
int remtarget = target%25;
if (remtarget >= 10)
{
if (remtarget % 10 == 0)
{
count += remtarget/10;
map.put(dime, remtarget/10);
return count;
}
else
{
count += remtarget/10;
map.put(dime, remtarget/10);
int fivetarget = remtarget%10;
if (fivetarget >= 5)
{
if (fivetarget % 5 == 0)
{
count += fivetarget/5;
map.put(nickel, fivetarget/5);
}
else
{
count += fivetarget/5;
map.put(nickel, fivetarget/5);
int ones = fivetarget%5;
count+= ones;
map.put(cent, ones);
}
}
else
{
count += fivetarget;
map.put(cent, fivetarget);
return count;
}
}
}
else
{
if (remtarget >= 5)
{
if (remtarget % 5 == 0)
{
count += remtarget/5;
map.put(nickel, remtarget/5);
}
else
{
count += remtarget/5;
map.put(nickel, remtarget/5);
int ones = remtarget%5;
count+= ones;
map.put(cent, ones);
}
}
else
{
count += remtarget;
map.put(cent, remtarget);
return count;
}
}
}
}
else
{
if (target == 0)
{
return 0;
}
if (target >= 10)
{
if (target % 10 == 0)
{
count += target/10;
map.put(dime, target/10);
return count;
}
else
{
count += target/10;
map.put(dime, target/10);
int ftarget = target%10;
if (ftarget >= 5)
{
if (ftarget % 5 == 0)
{
count += ftarget/5;
map.put(nickel, ftarget/5);
}
else
{
count += ftarget/5;
map.put(nickel, ftarget/5);
int otarget = ftarget%5;
count+= otarget;
map.put(cent, otarget);
}
}
else
{
count += ftarget;
map.put(cent, ftarget);
return count;
}
}
}
else
{
if (target > 5)
{
if (target % 5 == 0)
{
count += target/5;
map.put(nickel, target/5);
}
else
{
count += target/5;
map.put(nickel, target/5);
int o = target%5;
count+= o;
map.put(cent, o);
}
}
else
{
count += target;
map.put(cent, target);
return count;
}
}
}
return count;
}
}

Related

Competitive programming - Prepare the perfect curry with ingredients P, Q, and R

Recently i got a competetive programming task which i couldn't manage to complete. Just curious to know the best solution for the problem
"A" is a zero-indexed array of N integers.
Elements of A are integers within the range [−99,999,999 to 99,999,999]
The 'curry' is a string consisting of N characters such that each character is either 'P', 'Q' or 'R' and the
corresponding index of the array is the weight of each ingredient.
The curry is perfect if the sum of the total weights of 'P', 'Q' and 'R' is equal.
write a function
makeCurry(Array)
such that, given a zero-indexed array Array consisting of N integers, returns the perfect curry of this array.
The function should return the string "noLuck" if no perfect curry exists for that Array.
For example, given array Array such that
A[0] = 3 A[1] = 7 A[2] = 2 A[3] = 5 A[4] = 4
the function may return "PQRRP", as explained above. Given array A such that
A[0] = 3 A[1] = 6 A[2] = 9
the function should return "noLuck".
The approach i tried was this
import collections
class GetPerfectCurry(object):
def __init__(self):
self.curry = ''
self.curry_stats = collections.Counter({'P': 0, 'Q': 0, 'R': 0})
pass
def get_perfect_curry(self, A):
if len(A) == 0:
return "noLuck"
A.sort(reverse=True)
for i, ele in enumerate(A):
self.check_which_key_to_add_new_element_and_add_element(ele)
if self.curry_stats['P'] == self.curry_stats['Q'] == self.curry_stats['R']:
return self.curry
else:
return "noLuck"
def check_which_key_to_add_new_element_and_add_element(self, val):
# get the maximum current value
# check if addition of new value with any of the other two key equals the max value
# if yes then add that value and append the key in the curry string
current_max_key = max(self.curry_stats, key=self.curry_stats.get)
check_for_equality = False
key_to_append = None
for key, ele in enumerate(self.curry_stats):
if ele != current_max_key:
if self.curry_stats[ele] + val == self.curry_stats[current_max_key]:
check_for_equality = True
key_to_append = ele
if check_for_equality:
self.curry_stats.update(str(key_to_append) * val)
self.curry += str(key_to_append)
pass
else:
# if no value addition equals the current max
# then find the current lowest value and add it to that key
current_lowest_key = min(self.curry_stats, key=self.curry_stats.get)
self.curry_stats.update(str(current_lowest_key)*val)
self.curry += str(current_lowest_key)
if __name__ == '__main__':
perfect_curry = GetPerfectCurry()
A = [3, 7, 2, 5, 4]
# A = [3, 6, 9]
# A = [2, 9, 6, 3, 7]
res = perfect_curry.get_perfect_curry(A)
print(res)
But it was incorrect. Scratching my head for the past four hours for the best solution for this problem
A possible algorithm is as follows:
Sum the weights. If it's not a multiple of 3, no luck. If it is, divide by 3 to get the target.
Find subsets of A that add up to target. For such subsets, remove it and you get B. Find a subset of B that adds up to target.
Here's a Java implementation (I'm not a Python guy, sorry):
import java.util.Arrays;
public class Main
{
// Test if selected elements add up to target
static boolean check(int[] a, int selection, int target)
{
int sum = 0;
for(int i=0;i<a.length;i++)
{
if(((selection>>i) & 1) == 1)
sum += a[i];
}
return sum==target;
}
// Remove the selected elements
static int[] exclude(int[] a, int selection)
{
int[] res = new int[a.length];
int j = 0;
for(int i=0;i<a.length;i++)
{
if(((selection>>i) & 1) == 0)
res[j++] = a[i];
}
return Arrays.copyOf(res, j);
}
static String getCurry(int[] a)
{
int sum = 0;
for(int x : a)
sum += x;
if(sum%3 > 0)
return "noLuck";
int target = sum/3;
int max1 = 1<<a.length; // 2^length
for(int i=0;i<max1;i++)
{
if(check(a, i, target))
{
int[] b = exclude(a, i);
int max2 = 1<<b.length; // 2^length
for(int j=0;j<max2;j++)
{
if(check(b, j, target))
return formatSolution(i, j, a.length);
}
}
}
return "noLuck";
}
static String formatSolution(int p, int q, int len)
{
char[] res = new char[len];
Arrays.fill(res, 'R');
int j = 0;
for(int i=0;i<len;i++)
{
if(((p>>i) & 1) == 1)
res[i] = 'P';
else
{
if(((q>>j) & 1) == 1)
res[i] = 'Q';
j++;
}
}
return new String(res);
}
public static void main(String[] args)
{
// int[] a = new int[]{3, 7, 2, 5, 4};
// int[] a = new int[]{1, 1, 2, -1};
int[] a = new int[]{5, 4, 3, 3, 3, 3, 3, 3};
System.out.println(getCurry(a));
}
}
You can test it here.
Hereafter so many years I'm writing code for js for needed people. (TBH I took the ref of the accepted answer)
As he mentioned, A possible algorithm is as follows:
Sum the weights. If it's not a multiple of 3, no luck. If it is, divide by 3 to get the target.
Find subsets of A that add up to target. For such subsets, remove it and you get B. Find a subset of B that adds up to target.
// Test if selected elements add up to target
function check(a, selection, target)
{
let sum = 0;
for(let i=0;i<a.length;i++)
{
if(((selection>>i) & 1) == 1)
sum += a[i];
}
return sum==target;
}
// Remove the selected elements
function exclude(a, selection)
{
let res = [a.length];
let j = 0;
for(let i=0;i<a.length;i++)
{
if(((selection>>i) & 1) == 0)
res[j++] = a[i];
}
return res
}
function getCurry(a)
{
let sum = a.reduce((accumulator, currentValue) => accumulator + currentValue);
if(sum%3 > 0)
return "noLuck";
let target = sum/3;
let max1 = 1<<a.length; // 2^length
for(let i=0;i<max1;i++)
{
if(check(a, i, target))
{
let b = exclude(a, i);
let max2 = 1<<b.length; // 2^length
for(let j=0;j<max2;j++)
{
if(check(b, j, target))
return formatSolution(i, j, a.length);
}
}
}
return "noLuck";
}
function formatSolution(p, q, len)
{
let res = new Array(len)
res.fill('R')
let j = 0;
for(let i=0;i<len;i++)
{
if(((p>>i) & 1) == 1)
res[i] = 'P';
else
{
if(((q>>j) & 1) == 1)
res[i] = 'Q';
j++;
}
}
return new String(res);
}
// let a = [3, 7, 2, 5, 4]
// let a = [1, 1, 2, -1]
let a = [5, 4, 3, 3, 3, 3, 3, 3]
getCurry(a)

How can you determine how to place coins on a clock?

Say you are given a set of coins such as 4 10¢, 4 5¢, and 4 1¢.
You are asked to place these coins on a 12-hour analog clock face, where the next coin you place must be placed at X hours after the previous coin, where X is the value of the previous coin.
So if you place a 1¢ on 12, the next coin you place goes at 1. If you place a 5¢ on 1, the next coin you place goes at 6. And so on.
How can you maximize the number of coins that can be placed on the clock before the next coin would have to be placed in a slot that is already taken?
This is a problem I came across which I have been unable to solve except via exhaustive search. If the inputs are made to be arbitrary, exhaustive search fails quickly-- say it's an arbitrary number of coins of arbitrary various known denominations, with an arbitrary number of hours on the clock. Then you can't do exhaustive search anymore, because it becomes factorial time and fails on basis of excessive computational time requirements.
As maraca mentioned probably there isn't a much better solution than backtracking without more restrictions. Maybe with a larger number of coins of given denominations space can be covered with 'patterns'. Like coins [5, 10, 10, 5, 10, 10, 5, x] cover first 8 places and next coin is placed in similar location as first one. So the process can be repeated if there are enough coins.
Number of possible coin combinations in this case is not large at all. It is 12! / (4! * 4! * 4!) = 34650. For sure number explodes with larger parameters. Here is simple python code that solves 3 times larger problem which has possible coin combinations 3*10^15.
max_positions = []
max_order = None
def add_coin(coins, position, coin_order, occupied_positions, num_hours):
global max_positions, max_order
if position in occupied_positions or not coins:
# Can't place on that position or there is nothing more to place
if len(occupied_positions) > len(max_positions):
max_positions = occupied_positions
max_order = coin_order
return not coins # if all is covered return true to stop search
#
for c, num_coins in coins: # Try each coin
# Copy coins to new list and remove one used
c_coins = [x for x in coins if x[0] != c]
if num_coins > 1:
c_coins.append((c, num_coins-1))
# Next iteration
if add_coin(c_coins,
(position + c) % num_hours,
coin_order + [c],
occupied_positions + [position],
num_hours):
return True
def solve_coins(coins, num_hours):
global max_positions, max_order
max_positions = []
max_order = None
add_coin(coins, 0, [], [], num_hours)
print len(max_positions), max_positions, max_order
solve_coins([(1, 4), (5, 4), (10, 4)], 12)
solve_coins([(1, 8), (5, 8), (10, 8)], 24)
solve_coins([(1, 12), (5, 12), (10, 12)], 36)
output:
12 [0, 1, 6, 4, 2, 3, 8, 9, 7, 5, 10, 11] [1, 5, 10, 10, 1, 5, 1, 10, 10, 5, 1, 5]
24 [0, 1, 6, 16, 17, 3, 4, 14, 19, 5, 15, 20, 21, 2, 7, 8, 13, 18, 23, 9, 10, 11, 12, 22] [1, 5, 10, 1, 10, 1, 10, 5, 10, 10, 5, 1, 5, 5, 1, 5, 5, 5, 10, 1, 1, 1, 10, 10]
36 [0, 1, 6, 16, 17, 22, 23, 28, 2, 12, 13, 18, 19, 29, 34, 3, 8, 9, 10, 11, 21, 31, 5, 15, 20, 30, 35, 4, 14, 24, 25, 26, 27, 32, 33, 7] [1, 5, 10, 1, 5, 1, 5, 10, 10, 1, 5, 1, 10, 5, 5, 5, 1, 1, 1, 10, 10, 10, 10, 5, 10, 5, 5, 10, 10, 1, 1, 1, 5, 1, 10, 5]
// Expressing the coins as a list of buckets with the same modulo allows
// you to efficiently find the next coin to test and you don't start to
// calculate with the first penny and then do the same again starting
// with the second penny (or a 13-coin on a 12-clock), it is basically the same.
// Additionally it allows to remove and insert items at the current position in O(1).
// Also reverting is much better than copying whole states on each recursive call.
private class Bucket {
public int number;
public LinkedList<Integer> numbers = new LinkedList<>();
public Bucket(int number, int hours) {
this.number = number % hours;
numbers.add(number);
}
}
private LinkedList<Bucket> coins; // not using interface List as you are supposed to
private LinkedList<Integer> best, current; // because of removeLast()
private boolean[] occupied;
private int hours, limit;
public List<Integer> findBest(int[] coins, int hours) {
this.hours = hours;
// create buckets of coins with the same modulo
Integer[] c = Arrays.stream(coins).boxed().toArray( Integer[]::new );
// sort descending because a lot of small coins in a row are more likely to create
// an impassable area on the next pass around the clock
Arrays.sort(c, new Comparator<Integer>(){
public int compare(Integer a, Integer b) {
return Integer.compare(b.intValue() % hours, a.intValue() % hours);
}
});
this.coins = new LinkedList<>();
Bucket b = new Bucket(c[0].intValue(), hours);
this.coins.add(b);
int mod = c[0].intValue() % hours, coinCount = 1;
for (int i = 1; i < c.length; i++) {
int m = c[i].intValue() % hours;
if (m == mod) { // same bucket
b.numbers.add(c[i]);
} else { // new bucket
b = new Bucket(c[i].intValue(), hours);
this.coins.add(b);
mod = m;
}
coinCount++;
if (mod == 0) // don't need more than one 0 value
break;
}
best = new LinkedList<>();
current = new LinkedList<>();
occupied = new boolean[hours];
limit = coinCount < hours ? coinCount : hours; // max coins that can be placed
findBest(0);
return best;
}
private void findBest(int pos) {
if (best.size() == limit) // already found optimal solution
return;
if (occupied[pos] || current.size() == limit) {
if (current.size() > best.size())
best = (LinkedList<Integer>)current.clone();
return;
}
occupied[pos] = true;
for (int i = 0; i < coins.size(); i++) {
Bucket b = coins.get(i);
current.add(b.numbers.removeLast());
boolean removed = false;
if (b.numbers.size() == 0) { // bucket empty
coins.remove(i);
removed = true;
}
findBest((pos + b.number) % hours);
if (removed)
coins.add(i, b);
b.numbers.add(current.removeLast());
}
occupied[pos] = false;
}
Output for the given example: 10 10 5 1 1 1 5 10 10 1 5 5
Here is a slightly more optimized version in JavaScript where the list is implemented manually, so that you can really see why removing and adding the currend bucket is O(1). Because the list is always read in order it is superior to the array in this case. Whith an array you need to shift many elements or skip a lot of empty ones, depending how you implement it, not with a list of buckets. Should be a little easier to understand than the Java code.
var head, occupied, current, best, h, limit;
document.body.innerHTML = solve([1,1,1,1,5,5,5,5,10,10,10,10], 12);
function solve(coins, hours) {
h = hours;
coins.sort(function(a, b) {
let x = a % hours, y = b % hours;
if (x > y)
return -1;
if (x < y)
return 1;
return 0;
});
let mod = coins[0] % hours;
head = {num: mod, vals: [coins[0]], next: null};
let b = head, coinCount = 1;
for (let i = 1; i < coins.length && mod != 0; i++) {
let m = coins[i] % hours;
if (m == mod) {
b.vals.push(coins[i]);
} else {
b.next = {num: m, vals: [coins[i]], next: null};
b = b.next;
mod = m;
}
coinCount++;
}
limit = coinCount < hours ? coinCount : hours;
occupied = [];
for (let i = 0; i < hours; i++)
occupied.push(false);
best = [];
current = [];
solveRec(0);
return JSON.stringify(best);
}
function solveRec(pos) {
occupied[pos] = true;
let b = head, prev = null;
while (b !== null) {
let m = (pos + b.num) % h;
if (!occupied[m]) {
current.push(b.vals.pop());
let rem = false;
if (b.vals.length == 0) {
if (prev == null)
head = b.next;
else
prev.next = b.next;
rem = true;
}
solveRec(m);
if (current.length > best.length)
best = current.slice();
if (best.length == limit)
return;
if (rem) {
if (prev == null)
head = b;
else
prev.next = b;
}
b.vals.push(current.pop());
} else if (current.length + 1 > best.length) {
best = current.slice();
best.push(b.vals[b.vals.length - 1]);
}
prev = b;
b = b.next;
}
occupied[pos] = false;
}
I am still working on this, but it is already much better than O(n!). I will try to fit a new O() on it soon.
The concept is pretty simple, basically you create the smallest combos of numbers and then link them together into longer and longer strings of numbers until the next step is not possible.
A key to this working is that you don't track the front or end of a list of numbers, only the sum (and the inner sums due to their being calculated at earlier steps). so long as that sum is never divisible by clock, it will remain a clean solution.
Each step attempts to "splice" the smaller combos into the next size bigger:
(1,3), (3,1) -> (1,3,1), (3,1,3)
Here is a brief example (simplified) of what the algo is doing:
clock: 4
coins: 4
coins: 1,2,3,3
*bold pass, others are skipped for 1 of 3 reasons (not enough in population to build combo, sum divisible by clock, (in actual algo) prevent duplicates: (1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)
triples: (1,2,1), (2,1,2), (2,3,2), (3,2,3), (1,2,3), (2,3,3), (3,2,1), (3,3,2)
final combos:(1,2,3,x), (3,2,1,x)
This code is runnable standalone in c++ (but placeCoins is the algo):
I assume you will appropriate the algo to your purposes, but for anyone who wishes to run this cpp file, it will request clock size, coin count, and then after putting in coin count it will accept the next coin count number of inputs followed by enter as the coin values. The output will show the best counts, all orders at that count, and also during the algo it will show you the number of currently processing steps (which is where you can estimate complexity/ number of combos checked to see how much faster this is than exhaustive of any kind)
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <map>
using namespace std;
//min clock size 3
vector<vector<int>> placeCoins(int _clockSize, vector<int> _coins)
{
int totalCheckedCombos = 0;
vector<vector<int>> coinGroups;
vector<int> coinSet = _coins;
sort(coinSet.begin(), coinSet.end());
coinSet.erase(unique(coinSet.begin(), coinSet.end()), coinSet.end());
map<int, int> coinCounts;
for (int i = 0; i < coinSet.size(); i++)
{
coinCounts[coinSet.at(i)] = count(_coins.begin(), _coins.end(), coinSet.at(i));
}
cout << "pairs" << endl;
//generate fair pairs of coins
for (int i = 0; i < coinSet.size(); i++)
{
for (int ii = 0; ii < coinSet.size(); ii++)
{
if ((coinSet.at(i) + coinSet.at(ii)) % _clockSize != 0)
{
if (i == ii)
{
if (coinCounts[coinSet.at(i)] > 1)
{
coinGroups.push_back({ coinSet.at(i),coinSet.at(ii) });
}
}
else
{
coinGroups.push_back({ coinSet.at(i),coinSet.at(ii) });
}
}
}
}
cout << "combine" << endl;
//iteratively combine groups of coins
for (int comboSize = 3; comboSize < _clockSize; comboSize++)
{
totalCheckedCombos += coinGroups.size();
vector<vector<int>> nextSizeCombos;
for (int i = 0; i < coinGroups.size(); i++)
{
for (int ii = 0; ii < coinGroups.size(); ii++)
{
//check combo to match
bool match = true;
for (int a = 0; a < comboSize - 2; a++)
{
if (coinGroups.at(i).at(a+1) != coinGroups.at(ii).at(a))
{
match = false;
break;
}
}
//check sum
if (match)
{
vector<int> tempCombo = coinGroups.at(i);
int newVal = coinGroups.at(ii).at(coinGroups.at(ii).size()-1);
tempCombo.push_back(newVal);
if (coinCounts[newVal] >= count(tempCombo.begin(), tempCombo.end(), newVal))
{
if (accumulate(tempCombo.begin(), tempCombo.end(), 0) % _clockSize != 0)
{
nextSizeCombos.push_back(tempCombo);
}
}
}
}
}
if (nextSizeCombos.size() == 0)
{
//finished, no next size combos found
break;
}
else
{
cout << nextSizeCombos.size() << endl;
coinGroups = nextSizeCombos;
}
}
cout << "total combos checked: " << totalCheckedCombos << endl;
return coinGroups;
}
int main(int argc, char** argv) {
int clockSize;
int coinCount;
vector<int> coins = {};
cout << "enter clock size: " << endl;
cin >> clockSize;
cout << "count number: " << endl;
cin >> coinCount;
for (int i = 0; i < coinCount; i++)
{
int tempCoin;
cin >> tempCoin;
coins.push_back(tempCoin);
}
cout << "press enter to compute combos: " << endl;
cin.get();
cin.get();
vector<vector<int>> resultOrders = placeCoins(clockSize, coins);
for (int i = 0; i < resultOrders.size(); i++)
{
cout << resultOrders.at(0).size()+1 << endl;
for (int ii = 0; ii < resultOrders.at(i).size(); ii++)
{
cout << resultOrders.at(i).at(ii) << " , ";
}
cout <<"x"<< endl;
}
cin.get();
cin.get();
}
ps: although I debugged this to a stable state, it still could definitely use fine tuning and optimization, but that is variable to different languages, so I just got the algo to work and called it good enough. If you see something glaringly wrong or poor form, feel free to comment and i'll fix it (or edit it directly if you want).
Instead of a greedy approach, try the maximum result of choosing a coin vs. not choosing a coin.
def valueOfClock(capacity, coins, n, hour):
if (n == 0 or capacity == 0 or hour > 12):
return 0
# Choose next coin if value is greater than the capacity
if (coins[n-1] > capacity):
valueOfClock(capacity, coins, n-1, hours)
# Choose max value of either choosing the next coin or
# choosing the current coin
return max(valueOfClock(capacity, coins, n-1, hours),
valueOfClock(capacity-coins[n-1], coins, n-1, hours + coins[n-1]))

Algorithm puzzle: minimum cost for allow all persons standing on a line to communicate with each other

I have a algorithm design puzzle that I could not solve.
The puzzle is formulated like this: There are N persons standing on a number line, each of them maybe standing on any integer number on that line. Multiple persons may stand on the same number. For any two persons to be able to communicate with each other, the distance between them should be less than K. The goal is to move them so that each pair of two persons can communicate each other (possibly via other people). In other words, we need to move them so that the distance between any neighboring two persons is smaller than K.
Question: What is the minimum number of total moves? It feels like this falls into greedy algorithm family or dynamic programming. Any hints are appreciated!
We can do the following in O(n):
Calculate the cost of moving all people to the right of person i towards person i at an acceptable distance:
costRight(A[i]) = costRight(A[i+1]) + (A[i+1] - A[i] - k + 1) * count of people to the right
K = 3; A = { 0, 3, 11, 17, 21}
costRight = {32, 28, 10, 2, 0}
Calculate the cost of moving all people to the left of person i towards person i at an acceptable distance:
costLeft(A[i]) = costLeft(A[i-1]) + (A[i] - A[i-1] - k + 1) * count of people to the left
K = 3; A = { 0, 3, 11, 17, 21}
costLeft = { 0, 1, 13, 25, 33}
costRight = {32, 28, 10, 2, 0}
Now that we have cost from both directions we can do this in O(n):
minCost = min(costRight + costLeft) for all A[i]
minCost = min(32 + 0, 28 + 1, 13 + 10, 25 + 2, 33 + 0) = 23
But sometimes that's no enough:
K = 3; A = { 0, 0, 1, 8, 8}
carry: -2 -4 3
costLeft = { 0, 0, 0, 11, 11}
carry: -3 5 -2
costRight = { 8, 8, 8, 0, 0}
The optimum is neither 11 nor 8. Test the current best by moving towards the greatest saving:
move 1 to 2, cost = 1
K = 3; A = { 0, 0, 2, 8, 8}
carry: -2 -2 -10
costLeft = { 0, 0, 0, 10, 10}
carry: -2 -2
costRight = { 6, 6, 6, 0, 0}
minCost = 1 + min(0 + 6, 0 + 6, 0 + 6, 10 + 0, 10 + 0) = 1 + 6 = 7
Not quite sure how to formularize this efficiently.
Here is a greedy algorithm written in Java, but I don't know if it gives the optimal solution in every case. Also it is more a proof of concept, there is some room for optimizations.
It is based on the fact that two neighbouring persons must not be more than K apart, the next neighbour must not be more than 2K away and so on. In each step we move the person that "violates these constraints most". The details of this calculation are in method calcForce.
package so;
import java.util.Arrays;
public class Main {
public static void main(String args[]) {
int[] position = new int[] {0, 0, 5, 11, 17, 23};
int k = 5;
solve(position, k);
}
private static void solve(int[] position, int k) {
if (!sorted(position)) {
throw new IllegalArgumentException("positions must be sorted");
}
int[] force = new int[position.length];
int steps = 0;
while (calcForce(position, k, force)) {
int mp = -1;
int mv = -1;
for (int i = 0; i < force.length; i++) {
if (mv < Math.abs(force[i])) {
mv = Math.abs(force[i]);
mp = i;
}
}
System.out.printf("move %d to the %s%n", mp, force[mp] > 0 ? "right" : "left");
if (force[mp] > 0) {
position[mp]++;
} else {
position[mp]--;
}
steps++;
}
System.out.printf("total: %d steps%n", steps);
}
private static boolean calcForce(int[] position, int k, int[] force) {
boolean commProblem = false;
Arrays.fill(force, 0);
for (int i = 0; i < position.length - 1; i++) {
for (int j = i + 1; j < position.length; j++) {
int f = position[j] - position[i] - (j - i) * k;
if (f > 0) {
force[i] += f;
force[j] -= f;
commProblem = true;
}
}
}
return commProblem;
}
private static boolean sorted(int[] position) {
for (int i = 0; i < position.length - 1; i++) {
if (position[i] > position[i+1]) {
return false;
}
}
return true;
}
}

Find all M-length sets of positive integers that sum to N

The problem I'm trying to solve is how do we find all the integer sets [a1, a2, ... ,am] so that
a1 + a2 + ... + am = N
and with the constraint ai >= 1
For example if M = 4, and N = 7 there are three answers
[1,1,1,4]
[1,1,2,3]
[1,2,2,2]
Since you have to print all the sets that sum to N. You can employ a complete search algorithm using recursion. In the following code, M is the number of numbers in the set and N is the sum required.
int M;
int N;
void run(){
M = 4;
N = 7;
int[] arr = new int[M];
print(arr, 0, N, 1);
}
// req holds the required sum for the numbers in the array from arr[from]
// to arr[M-1].
// "last" holds the last value that we had put in the array.
// The first call to the array will be with last=1.
void print(int[] arr, int from, int req, int last){
// Reached the end of the array and sum required 0.
if(from==M && req==0){
System.out.println(Arrays.toString(arr));
return;
}
// Either reached the end of the array but sum is not equal to N
// Or if we have not reached the end of the array but sum has already
// become more than or equal to N.
if(from==M || req<=0){
return;
}
for(int i=last; i<=req; i++){
arr[from] = i;
print(arr, from+1, req-i, i);
}
}
Output for M=4 and N=7:
[1, 1, 1, 4]
[1, 1, 2, 3]
[1, 2, 2, 2]
Output for M=3 and N=10:
[1, 1, 8]
[1, 2, 7]
[1, 3, 6]
[1, 4, 5]
[2, 2, 6]
[2, 3, 5]
[2, 4, 4]
[3, 3, 4]
Answer for the problem in the link, just got accepted.
The idea is simple, assume that we know the maximum value for each section is X, and we want to find a way to divide these cabinets to achieve that , we can greedily divide them as follow:
Starting from first cabinet, iterating through each cabinet, until the total from first to ith cabinet is greater than X. So this is the first section, similarly, we can select other sections. This greedy will always find a solution (if exists).
Finally, we can using binary search to adjust the value of X, decrease X if we can find a way to divide the cabinets, or increase X if we cannot find one.
Here is the code in Java:
public class FairWorkload {
public int getMostWork(int[] folders, int workers) {
int[] data = new int[folders.length];
data[0] = folders[0];
for (int i = 1; i < data.length; i++) {
data[i] = data[i - 1] + folders[i];
}
if (workers == 1) {
return data[data.length - 1];
}
int start = 0;
int end = data[data.length - 1];
int result = Integer.MAX_VALUE;
while (start <= end) {
int mid = (start + end) / 2;
int index = 0;
for (int k = 0; k < workers && index < data.length; k++) {
int less = index > 0 ? data[index - 1] : 0;
int temp = index;
for (int i = index; i < data.length; i++) {
if (data[i] - less <= mid) {
temp = i;
} else {
break;
}
}
// System.out.println(data[temp] - less + " " + mid);
if(data[temp] - less > mid){
index = -1;
break;
}
index = temp + 1;
}
//System.out.println(mid + " " + index);
if (index != data.length) {
start = mid + 1;
} else {
result = Math.min(result, mid);
end = mid - 1;
}
}
return result;
}
public static void main(String[] args) {
int[] data = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1000};
System.out.println(new FairWorkload().getMostWork(data, 2));
}
}
One possible solution uses a counting technique, finding the rightmost term that satisfies [i] <= [length-1] - 2, and then flattening out all other terms to the right as much as possible, keeping a[i] <= a[i+1].
import java.util.Arrays;
public class test {
public static void main(String[] args) {
test t = new test();
t.go();
}
private void go() {
int w = 3;
int sum = 10;
int[] terms = new int[w];
for (int i = 0; i < terms.length; i++) {
terms[i] = 1;
}
terms[w-1] = sum - w + 1;
System.out.println(Arrays.toString(terms));
for (int i = right_index(terms); i>=0; i = right_index(terms)) {
terms[i]++;
int a = terms[i];
int overflow = -1;
// balance all the terms to the right
for (int j = i+1; j < terms.length-1; j++) {
overflow += terms[j] - a;
terms[j] = a;
}
terms[terms.length-1] += overflow;
System.out.println(Arrays.toString(terms));
}
}
// find the rightmost index i, where [i] <= [ia.length-1] - 2
private int right_index(int[] ia) {
int max = ia[ia.length-1];
for (int i = ia.length - 1; i >= 0; i--) {
if (ia[i] <= max - 2)
return i;
}
return -1;
}
}

Find longest increasing sequence

You are given a sequence of numbers and you need to find a longest increasing subsequence from the given input(not necessary continuous).
I found the link to this(Longest increasing subsequence on Wikipedia) but need more explanation.
If anyone could help me understand the O(n log n) implementation, that will be really helpful. If you could explain the algo with an example, that will be really appreciated.
I saw the other posts as well and what I did not understand is:
L = 0
for i = 1, 2, ... n:
binary search for the largest positive j ≤ L such that X[M[j]] < X[i] (or set j = 0 if no such value exists)
above statement, from where to start binary search? how to initialize M[], X[]?
A simpler problem is to find the length of the longest increasing subsequence. You can focus on understanding that problem first. The only difference in the algorithm is that it doesn't use the P array.
x is the input of a sequence, so it can be initialized as:
x = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
m keeps track of the best subsequence of each length found so far. The best is the one with the smallest ending value (allowing a wider range of values to be added after it). The length and ending value is the only data needed to be stored for each subsequence.
Each element of m represents a subsequence. For m[j],
j is the length of the subsequence.
m[j] is the index (in x) of the last element of the subsequence.
so, x[m[j]] is the value of the last element of the subsequence.
L is the length of the longest subsequence found so far. The first L values of m are valid, the rest are uninitialized. m can start with the first element being 0, the rest uninitialized. L increases as the algorithm runs, and so does the number of initialized values of m.
Here's an example run. x[i], and m at the end of each iteration is given (but values of the sequence are used instead of indexes).
The search in each iteration is looking for where to place x[i]. It should be as far to the right as possible (to get the longest sequence), and be greater than the value to its left (so it's an increasing sequence).
0: m = [0, 0] - ([0] is a subsequence of length 1.)
8: m = [0, 0, 8] - (8 can be added after [0] to get a sequence of length 2.)
4: m = [0, 0, 4] - (4 is better than 8. This can be added after [0] instead.)
12: m = [0, 0, 4, 12] - (12 can be added after [...4])
2: m = [0, 0, 2, 12] - (2 can be added after [0] instead of 4.)
10: m = [0, 0, 2, 10]
6: m = [0, 0, 2, 6]
14: m = [0, 0, 2, 6, 14]
1: m = [0, 0, 1, 6, 14]
9: m = [0, 0, 1, 6, 9]
5: m = [0, 0, 1, 5, 9]
13: m = [0, 0, 1, 5, 9, 13]
3: m = [0, 0, 1, 3, 9, 13]
11: m = [0, 0, 1, 3, 9, 11]
7: m = [0, 0, 1, 3, 7, 11]
15: m = [0, 0, 1, 3, 7, 11, 15]
Now we know there is a subsequence of length 6, ending in 15. The actual values in the subsequence can be found by storing them in the P array during the loop.
Retrieving the best sub-sequence:
P stores the previous element in the longest subsequence (as an index of x), for each number, and is updated as the algorithm advances. For example, when we process 8, we know it comes after 0, so store the fact that 8 is after 0 in P. You can work backwards from the last number like a linked-list to get the whole sequence.
So for each number we know the number that came before it. To find the subsequence ending in 7, we look at P and see that:
7 is after 3
3 is after 1
1 is after 0
So we have the subsequence [0, 1, 3, 7].
The subsequences ending in 7 or 15 share some numbers:
15 is after 11
11 is after 9
9 is after 6
6 is after 2
2 is after 0
So we have the subsequences [0, 2, 6, 9, 11], and [0, 2, 6, 9, 11, 15] (the longest increasing subsequence)
One of the best explanation to this problem is given by MIT site.
http://people.csail.mit.edu/bdean/6.046/dp/
I hope it will clear all your doubts.
based on FJB's answer, java implementation:
public class Lis {
private static int[] findLis(int[] arr) {
int[] is = new int[arr.length];
int index = 0;
is[0] = index;
for (int i = 1; i < arr.length; i++) {
if (arr[i] < arr[is[index]]) {
for (int j = 0; j <= index; j++) {
if (arr[i] < arr[is[j]]) {
is[j] = i;
break;
}
}
} else if (arr[i] == arr[is[index]]) {
} else {
is[++index] = i;
}
}
int[] lis = new int[index + 1];
lis[index] = arr[is[index]];
for (int i = index - 1; i >= 0; i--) {
if (is[i] < is[i + 1]) {
lis[i] = arr[is[i]];
} else {
for (int j = is[i + 1] - 1; j >= 0; j--) {
if (arr[j] > arr[is[i]] && arr[j] < arr[is[i + 1]]) {
lis[i] = arr[j];
is[i] = j;
break;
}
}
}
}
return lis;
}
public static void main(String[] args) {
int[] arr = new int[] { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11,
7, 15 };
for (int i : findLis(arr)) {
System.out.print(i + "-");
}
System.out.println();
arr = new int[] { 1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 };
for (int i : findLis(arr)) {
System.out.print(i + "-");
}
System.out.println();
}
}
Below is the O(NLogN) longest increasing subsequence implementation:
// search for the index which can be replaced by the X. as the index can't be
//0 or end (because if 0 then replace in the findLIS() and if it's greater than the
//current maximum the just append)of the array "result" so most of the boundary
//conditions are not required.
public static int search(int[] result, int p, int r, int x)
{
if(p > r) return -1;
int q = (p+r)/2;
if(result[q] < x && result[q+1]>x)
{
return q+1;
}
else if(result[q] > x)
{
return search(result, p, q, x);
}
else
{
return search(result, q+1, r, x);
}
}
public static int findLIS(int[] a)
{
int[] result = new int[a.length];
result[0] = a[0];
int index = 0;
for(int i=1; i<a.length; i++)
{
int no = a[i];
if(no < result[0]) // replacing the min number
{
result[0] = no;
}
else if(no > result[index])//if the number is bigger then the current big then append
{
result[++index] = no;
}
else
{
int c = search(result, 0, index, no);
result[c] = no;
}
}
return index+1;
}
Late to the party, but here's a JavaScript implementation to go along with the others.. :)
var findLongestSubsequence = function(array) {
var longestPartialSubsequences = [];
var longestSubsequenceOverAll = [];
for (var i = 0; i < array.length; i++) {
var valueAtI = array[i];
var subsequenceEndingAtI = [];
for (var j = 0; j < i; j++) {
var subsequenceEndingAtJ = longestPartialSubsequences[j];
var valueAtJ = array[j];
if (valueAtJ < valueAtI && subsequenceEndingAtJ.length > subsequenceEndingAtI.length) {
subsequenceEndingAtI = subsequenceEndingAtJ;
}
}
longestPartialSubsequences[i] = subsequenceEndingAtI.concat();
longestPartialSubsequences[i].push(valueAtI);
if (longestPartialSubsequences[i].length > longestSubsequenceOverAll.length) {
longestSubsequenceOverAll = longestPartialSubsequences[i];
}
}
return longestSubsequenceOverAll;
};
Based on #fgb 's answer, I implemented the algorithm using c++ to find the longest strictly increasing sub-sequence. Hope this will be somewhat helpful.
M[i] is the index of the last element of the sequence whose length is i, P[i] is the index of the previous element of i in the sequence, which is used to print the whole sequence.
main() is used to run the simple test case: {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}.
#include <vector>
using std::vector;
int LIS(const vector<int> &v) {
int size = v.size(), max_len = 1;
// M[i] is the index of the last element of the sequence whose length is i
int *M = new int[size];
// P[i] is the index of the previous element of i in the sequence, which is used to print the whole sequence
int *P = new int[size];
M[0] = 0; P[0] = -1;
for (int i = 1; i < size; ++i) {
if (v[i] > v[M[max_len - 1]]) {
M[max_len] = i;
P[i] = M[max_len - 1];
++max_len;
continue;
}
// Find the position to insert i using binary search
int lo = 0, hi = max_len - 1;
while (lo <= hi) {
int mid = lo + ((hi - lo) >> 1);
if (v[i] < v[M[mid]]) {
hi = mid - 1;
} else if (v[i] > v[M[mid]]) {
lo = mid + 1;
} else {
lo = mid;
break;
}
}
P[i] = P[M[lo]]; // Modify the previous pointer
M[lo] = i;
}
// Print the whole subsequence
int i = M[max_len - 1];
while (i >= 0) {
printf("%d ", v[i]);
i = P[i];
}
printf("\n");
delete[] M, delete[] P;
return max_len;
}
int main(int argc, char* argv[]) {
int data[] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
vector<int> v;
v.insert(v.end(), data, data + sizeof(data) / sizeof(int));
LIS(v);
return 0;
}
The O(N lg N) solution comes from patience sorting of playing card. I found this from my code comment and hence sharing here. I believe it would be really easier to understand for everyone how it works. Also you can find all possible longest increasing sub-sequence list if you understand well.
https://www.cs.princeton.edu/courses/archive/spring13/cos423/lectures/LongestIncreasingSubsequence.pdf
Code:
vector<int> lisNlgN(vector<int> v) {
int n = v.size();
vector<int> piles = vector<int>(n, INT_MAX);
int maxLen = 0;
for(int i = 0; i < n; i++) {
int pos = lower_bound(piles.begin(), piles.end(), v[i]) - piles.begin();
piles[pos] = v[i];
maxLen = max(maxLen, pos+1); // Plus 1 because of 0-based index.
}
// // Print piles for debug purpose
// for (auto x : piles) cout << x << " ";
// cout << endl;
//
// // Print position for debug purpose
// for (auto x : position) cout << x << " ";
// cout << endl;
vector<int> ret = vector<int>(piles.begin(), piles.begin() + maxLen);
return ret;
}
Code:
vector<vector<int>> allPossibleLIS(vector<int> v) {
struct Card {
int val;
Card* parent = NULL;
Card(int val) {
this->val = val;
}
};
auto comp = [](Card* a, Card* b) {
return a->val < b->val;
};
int n = v.size();
// Convert integers into card node
vector<Card*> cards = vector<Card*>(n);
for (int i = 0; i < n; i++) cards[i] = new Card(v[i]);
vector<Card*> piles = vector<Card*>(n, new Card(INT_MAX));
vector<Card*> lastPileCards;
int maxLen = 0;
for(int i = 0; i < n; i++) {
int pos = lower_bound(piles.begin(), piles.end(), new Card(v[i]), comp) - piles.begin();
piles[pos] = cards[i];
// Link to top card of left pile
if (pos == 0) cards[i]->parent = NULL;
else cards[i]->parent = piles[pos-1];
// Plus 1 because of 0-based index.
if (pos+1 == maxLen) {
lastPileCards.push_back(cards[i]);
} else if (pos+1 > maxLen) {
lastPileCards.clear();
lastPileCards.push_back(cards[i]);
maxLen = pos + 1;
}
}
// Print for debug purpose
// printf("maxLen = %d\n", maxLen);
// printf("Total unique lis list = %d\n", lastPileCards.size());
vector<vector<int>> ret;
for (auto card : lastPileCards) {
vector<int> lis;
Card* c = card;
while (c != NULL) {
lis.push_back(c->val);
c = c->parent;
}
reverse(lis.begin(), lis.end());
ret.push_back(lis);
}
return ret;
}

Resources