Two Egg problem:
You are given 2 eggs.
You have access to a 100-storey building.
Eggs can be very hard or very fragile means it may break if dropped from the first floor or may not even break if dropped from 100 th floor.Both eggs are identical.
You need to figure out the highest floor of a 100-storey building an egg can be dropped without breaking.
Now the question is how many drops you need to make. You are allowed to break 2 eggs in the process.
I know the solution for this problem with dynamic programming. I want to trace the solution along with the minimum number of tries. i.e the floors that I have to try for getting the minimum number of tries.
# include <stdio.h>
# include <limits.h>
// A utility function to get maximum of two integers
int max(int a, int b) { return (a > b)? a: b; }
/* Function to get minimum number of trails needed in worst
case with n eggs and k floors */
int eggDrop(int n, int k)
{
/* A 2D table where entery eggFloor[i][j] will represent minimum
number of trials needed for i eggs and j floors. */
int eggFloor[n+1][k+1];
int res;
int i, j, x;
// We need one trial for one floor and0 trials for 0 floors
for (i = 1; i <= n; i++)
{
eggFloor[i][1] = 1;
eggFloor[i][0] = 0;
}
// We always need j trials for one egg and j floors.
for (j = 1; j <= k; j++)
eggFloor[1][j] = j;
// Fill rest of the entries in table using optimal substructure
// property
for (i = 2; i <= n; i++)
{
for (j = 2; j <= k; j++)
{
eggFloor[i][j] = INT_MAX;
for (x = 1; x <= j; x++)
{
res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x]);
if (res < eggFloor[i][j])
eggFloor[i][j] = res;
}
}
}
// eggFloor[n][k] holds the result
return eggFloor[n][k];
}
/* Driver program to test to pront printDups*/
int main()
{
int n = 2, k = 36;
printf ("\nMinimum number of trials in worst case with %d eggs and "
"%d floors is %d \n", n, k, eggDrop(n, k));
return 0;
}
You just need to store the value of x that gives you the optimal solution:
int eggDrop(int n, int k)
{
/* A 2D table where entery eggFloor[i][j] will represent minimum
number of trials needed for i eggs and j floors. */
int eggFloor[n+1][k+1];
int floor[n+1][k+1];
int res;
int i, j, x;
// We need one trial for one floor and0 trials for 0 floors
for (i = 1; i <= n; i++)
{
eggFloor[i][1] = 1;
eggFloor[i][0] = 0;
}
// We always need j trials for one egg and j floors.
for (j = 1; j <= k; j++)
eggFloor[1][j] = j;
// Fill rest of the entries in table using optimal substructure
// property
for (i = 2; i <= n; i++)
{
for (j = 2; j <= k; j++)
{
eggFloor[i][j] = INT_MAX;
for (x = 1; x <= j; x++)
{
res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x]);
if (res < eggFloor[i][j]) {
eggFloor[i][j] = res;
floor[i][j] = x;
}
}
}
}
// eggFloor[n][k] holds the result
return eggFloor[n][k];
}
In the end, floor[i][j] contains the floor you need to try when you have i eggs and j floors.
Related
I was trying to solve this proble:
A gallery with plants is divided into n parts, numbered : 0,1,2,3...n-1. There are provisions for attaching water sprinklers at every partition. A sprinkler with range x at partition i can water all partitions from i-x to i+x.
Given an array gallery[ ] consisting of n integers, where gallery[i] is the range of sprinkler at partition i (power==-1 indicates no sprinkler attached), return the minimum number of sprinklers that need to be turned on to water the complete gallery.
If there is no possible way to water the full length using the given sprinklers, print -1.
and this is how I ended up trying-
Create a frequency array such that the ith element contains the number of sprinklers that are watering the ith part of the gallery.
If any element of this array is zero after going through all the sprinklers, then return -1 as even if all the sprinklers tried they couldn't water each part.
Then, std::stable_sort all the sprinklers based on their range, in increasing order.
Then, remove a sprinkler if it is redundant, starting from the smallest range to the largest.
My implementation of the same-
typedef struct sprinkler {
int l;
int r;
} sprinkler;
int min_sprinklers(int gallery[], int n)
{
int freq[n];
vector<sprinkler> vec;
for(int i = 0; i < n; i++) freq[i] = 0;
for(int i = 0 ; i < n; i++) {
int x = gallery[i];
if(x == -1) continue;
int l = max(0, i - x);
int r = min(n-1, i + x);
sprinkler s;
s.l = l;
s.r = r;
vec.push_back(s);
for(int j = l; j <= r; j++) {
freq[j]++;
}
}
for(int i = 0; i < n; i++) {
if(freq[i] == 0) return -1;
}
stable_sort(vec.begin(), vec.end(), [](sprinkler s1, sprinkler s2) { return s1.r-s1.l < s2.r-s2.l; });
int sprinklers = vec.size();
for(int i = 0; i < vec.size(); i++) {
int l = vec[i].l;
int r = vec[i].r;
bool flag = false;
for(int j = l; j <= r; j++) {
if(freq[j] == 1) {
flag = true;
break;
}
}
if(!flag) {
for(int j = l; j <= r; j++) freq[j]--;
sprinklers--;
}
}
return sprinklers;
}
But I still seem to be missing something and still don't know what.
Link to try my code:
https://practice.geeksforgeeks.org/problems/410d51d667ab93f2219b15126f001f32e8bb029e/0/?category[]=Greedy&category[]=Greedy&difficulty[]=1&page=1&query=category[]Greedydifficulty[]1page1category[]Greedy#
I faced this problem in an interview challenge
K caterpillars are eating their way through N leaves, each caterpillar
falls from leaf to leaf in a unique sequence, all caterpillars start
at a twig at position 0 and falls onto the leaves at position between
1 and N. Each caterpillar j has an associated jump number Aj. A
caterpillar with jump number j eats leaves at positions that are
multiple of j. It will proceed in the order j, 2j, 3j…. till it
reaches the end of the leaves and it stops and build its cocoon. Given
a set A of K elements , we need to determine the number
of uneaten leaves.
Constraints:
1 <= N <= 109
1 <= K <= 15
1 <= A[i] <= 109
Input format:
N = No of uneaten leaves.
K = No. of caterpillars.
A = Array of integer.
jump numbers Output:
The integer nu. Of uneaten leaves
Sample Input:
10
3
2
4
5
Output:
4
Explanation:
[2, 4, 5] is the 3-member set of jump numbers. All leaves which are multiple of 2, 4, and 5 are eaten. Only 4 leaves which are numbered 1,3,7,9 are left.
the naive approach for solving this question is have a Boolean array of all N numbers, and iterate over every caterpillar and remember the eaten leaves by it.
int uneatenusingNaive(int N, vector<int> A)
{
int eaten = 0;
vector<bool>seen(N+1, false);
for (int i = 0; i < A.size(); i++)
{
long Ai = A[i];
long j = A[i];
while (j <= N && j>0)
{
if (!seen[j])
{
seen[j] = true;
eaten++;
}
j += Ai;
}
}
return N - eaten;
}
this approach passed 8 out of 10 test cases and give wrong answer for 2 cases.
another approach using Inclusion Exclusion principle, explanation for it can be found here and here
below is my code for the second approach
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a%b);
}
int lcm(int i, int j)
{
return i*j / gcd(i, j);
}
vector<vector<int>> mixStr(vector<vector<int>> & mix, vector<int>& A, unordered_map<int, int> & maxStart)
{
vector<vector<int>> res;
if (mix.size() == 0)
{
for (int i = 0; i < A.size(); i++)
{
vector<int> tmp;
tmp.push_back(A[i]);
res.push_back(tmp);
}
return res;
}
for (int i = 0; i<mix.size(); i++)
{
int currSlotSize = mix[i].size();
int currSlotMax = mix[i][currSlotSize - 1];
for (int j = maxStart[currSlotMax]; j < A.size(); j++)
{
vector<int> tmp(mix[i]);
tmp.push_back(A[j]);
res.push_back(tmp);
}
}
return res;
}
int uneatenLeavs(int N, int k, vector<int> A)
{
int i = 0;
vector<vector<int>> mix;
bool sign = true;
int res = N;
sort(A.begin(), A.end());
unordered_map<int,int> maxStart;
for (int i = 0; i < A.size(); i++)
{
maxStart[A[i]] = i + 1;
}
int eaten = 0;
while (mix.size() != 1)
{
mix = mixStr(mix, A, maxStart);
for (int j = 0; j < mix.size(); j++)
{
int _lcm = mix[j][0];
for (int s = 1; s < mix[j].size(); s++)
{
_lcm = lcm(mix[j][s], _lcm);
}
if (sign)
{
res -= N / _lcm;
}
else
{
res += N / _lcm;
}
}
sign = !sign;
i++;
}
return res;
}
this approach passed only one 1/10 test case. and for the rest of test cases time limit exceeded and wrong answer.
Question:
What am I missing in first or second approach to be 100% correct.
Using Inclusion-Exclusion theorem is correct approach, however, your implementation seems to be too slow. We can use bitmasking technique to obtain a O(K*2^K) time complexity.
Take a look at this:
long result = 0;
for(int i = 1; i < 1 << K; i++){
long lcm = 1;
for(int j = 0; j < K; j++)
if(((1<<j) & i) != 0) //if bit j is set, compute new LCM after including A[j]
lcm *= A[j]/gcd(lcm, A[j]);
if(number of bit set in i is odd)
result += N/lcm;
else
result -= N/lcm;
}
For your first approach, an O(N*K) time complexity algorithm, with N = 10^9 and K = 15, it will be too slow, and can cause memory limit exceed/time limit exceed.
Notice that lcm can be larger than N, so, additional check is needed.
I am asked to find the largest product of 4 adjacent numbers horizontally, diagonally, or vertically, in a 20x20 grid for project euler problem 11. The grid can be found here:http://projecteuler.net/problem=11.
I could not find a more efficient approach than to loop over the entire array 4 times. I made a variable max that was initially set equal to 0. I then looped over the array horizontally, and found the products. If a product was greater than max, max was set to that product, etc. I did this for all 4 loops. However, my answer is wrong, and probably too big.
#include <iostream>
using namespace std;
int main () {
int twenty_grid[20][20] =
{
{ 8, 2, 22, /* data elided since the question links to it */ },
…
}
int max = 0;
// Pass 1: This determines the greatest element horizontally
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 17; ++j) {
// j stops at 17 to avoid a segmentation fault.
int n = twenty_grid[i][j] *
twenty_grid[i][j+1] *
twenty_grid[i][j+2] *
twenty_grid[i][j+2] *
twenty_grid[i][j+3];
if (n > max)
max = n;
}
}
// Now we do the same loop, except we do i + 1, i + 2, etc,
// rather than j +1, j+2. This does it vertically. Pass 2:
for (int i = 0; i < 17; ++i) {
for (int j = 0; j < 20; ++j) {
int n = twenty_grid[i][j] *
twenty_grid[i+1][j] *
twenty_grid[i+2][j] *
twenty_grid[i+3][j];
if (n > max) {
max = n;
}
}
}
// Finally, we increment both i and j to get the diagonals.
for (int i = 0; i < 17; ++i) {
for (int j = 0; j < 20; ++j) {
int n = twenty_grid[i][j] *
twenty_grid[i+1][j+1] *
twenty_grid[i+2][j+2] *
twenty_grid[i+3][j+3];
if (n > max) {
max = n;
}
}
}
// For diagonals, 2 passes are needed to account for both directions.
for (int i = 0; i < 17; i++) {
for (int j = 3; j < 20; j++) {
int n = twenty_grid[i][j] *
twenty_grid[i + 1][i -1] *
twenty_grid[i + 2][i -2] *
twenty_grid[i + 3][i -3];
if (n > max)
max = n;
}
}
cout << max << endl;
return 0;
}
To take a look at why my answer was constantly wrong, I began to print out each individual product as it was calculated. To my surprise, many of them were negative. After checking my loops, it doesn't seem like they access any data out of the array. Could someone lead me in the right direction for fixing this code?
I found several problems.
The first block of code multiplies twenty_grid[i][j+2] twice.
In the third block of code the end condition for the inner loop should be j < 17.
The last block of code uses i as an array index instead of j in three places.
It produces the correct answer after fixing these issues.
This code should produce a solved sudoku matrix, however the while statement puts it in an infinite loop. Removing the while statement gives me a matrix with some values still 99 or 0. And i can't generate 9 random numbers uniquely one by one.
IF YOU WANT TO RUN AND CHECK THE CODE, REMOVE THE WHILE STATEMENT.
int a[9][9];
int b[9][9];
int inputvalue(int x, int y, int value) //checks horizontally, vertically and 3*3matrix for conflicts
{
int i, j;
for (i = 0; i < 9; i++)
{
if (value == a[x][i] || value == a[i][y])
return 0;
}
for (i = (x / 3) * 3; i <= ((x / 3) * 3) + 2; i++)
{
for (j = (y / 3) * 3; j <= ((y / 3) * 3) + 2; j++)
if (b[i][j] == value)
return 0;
}
return value;
}
int main()
{
int i, j, k;
unsigned int s;
cout << "sudoku\n";
time_t t;
s = (unsigned) time(&t);
srand(s);
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
a[i][j] = 99;
}
for (i = 0; i < 9; i++)
{
for (j = 1; j <= 9; j++)//j is basically the value being given to cells in the matrix while k assigns the column no.
while(a[i][k]==99||a[i][k]==0)
{
k = rand() % 9;
a[i][k] = inputvalue(i, k, j);
}
}
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
getch();
}
You are using assignment =, instead of equality == here:
while(a[i][k]=99||a[i][k]=0)
^ ^
this should be:
while(a[i][k]==99||a[i][k]==0)
a[i][k]=99 will always evaluate to true since 99 is non-zero, although your original code does not compile for me under gcc as it is, so I suspect the code you are running either has some parenthesizes or is slightly different.
Also using k in the while loop before it is initialized is undefined behavior and it is unclear that your termination logic makes sense for a k that is constantly changing for each loop iteration.
Another source of the infinite loop is inputvalue which seems to get stuck returning 0 in some instances, so you need to tweak that a bit to prevent infinite loops.
Also, srand(time(NULL)); is a more common way to initialize the pseudo-random number generator
For some reason, this always returns value 1. The point of this is to find the starting number (1-1,000,000) that loops the most amount of times (until j = 1). j will always end up being 1 eventually (collatz theory), I divide j by 2 if it's even, or multiple by 3 and add 1 if it's odd.
#include <iostream>
using namespace std;
int collatz() {
int counter = 0;
int holder = 0;
for (int i = 999999; i > 1; i--){ // loops 999,999 times
for (int j = i; j != 1; counter++) { // loops until j = 1, records amount of loops
if (j % 2 == 0) { // if j is even, divide by 2, +1 to counter
j = j / 2;
} else {
j = (j*3) + 1; // if j is odd, multiply by 3 and add 1, +1 to counter
}
}
if (holder < counter){ // records highest number of loops
holder = counter;
counter = 0;
} else {
counter = 0;
}
}
return holder;
}
int main()
{
cout << collatz << endl;
return 0;
}
You're not calling your function, you're printing out the function pointer (which is converted to the bool value true (i.e. 1)).
First, use unsigned int or unsigned long long as the variable type of j to increase the arithmetic range.
Then, in the loop, check for overflow.
while (j!=1) {
counter++;
if (j % 2 == 0) {
j >>= 1;
} else {
unsigned int j2 = j;
j = (j*3) + 1;
if (j2 > j) {
return -1; // or surround this with try/catch/throw exception
}
}
}
With int i; the counter will overflow at i==113383;
and with unsigned int i; at 159487. If these are not checked, there's a possibility of infinite loop.