There are n stairs, a person standing at the bottom wants to reach the top. The person can climb either 1 stair or 2 stairs at a time.
Now I want to find the minimum number of steps needed that are divisible by given number m.
Here is the java program which I created using this as a reference, which is used to print the possible steps:
public static void main(String args[]) {
int n = 10, m = 2;
List<Integer> vals = new ArrayList<>();
Set<String> set = new TreeSet<>(Comparator.reverseOrder());
ClimbWays(n, 0, new int[n], vals, set);
set.forEach(a -> {
System.out.println(a + " : " + a.length());
});
}
public static void ClimbWays(int n, int currentIndex, int[] currectClimb, List<Integer> vals, Set<String> set) {
if (n < 0)
return;
if (n == 0) {
vals.add(currentIndex);
int last = 0;
StringBuilder sb = new StringBuilder();
for (int i = currentIndex - 1; i >= 0; i--) {
int current = currectClimb[i];
int res = current - last;
last = current;
sb.append(res);
}
String s = sb.toString();
char[] c = s.toCharArray();
Arrays.sort(c);
s = new String(c);
set.add(s);
return;
}
currectClimb[currentIndex] = n;
ClimbWays(n - 1, currentIndex + 1, currectClimb, vals, set);
ClimbWays(n - 2, currentIndex + 1, currectClimb, vals, set);
}
Output of the program is :
22222 : 5
112222 : 6
1111222 : 7
11111122 : 8
111111112 : 9
1111111111 : 10
Now for steps 10 if I want to get minimum steps divisible by m = 2, then the solution is 112222 which has 6 as the number of steps needed.
This program basically finds all possible pairs then add them to tree set. Next, I can loop through this set and get the minimum element divisible by given input m.
Is there a better approach to do this?
Since the person can climb a maximum of 2 steps at a time, the minimum number of steps to climb n stairs is
x = n/2 if n is even
x = n/2 + 1 if n is odd
Now you need to find the minimum number of steps to climb n stairs which is divisible by m. Meaning you need to find a number immediate next to x which is divisible by m.
if x%m == 0 then x is your answer
if x%m != 0 then ((x/m) + 1) * m is your answer.
Now speaking of your example
For n = 10,
x = n/2 = 5,
x%m = 5 % 2 = 1 != 0
Thus ans = ((5/2) + 1) * 2 = 6
Related
I am doing the following programming exercise: Strongest even number in an interval. The statement is:
A strongness of an even number is the number of times we can
successively divide by 2 until we reach an odd number starting with an
even number n.
For example, if n = 12, then
12 / 2 = 6
6 / 2 = 3
we divided successively 2 times and we reached 3, so the strongness of
12 is 2.
If n = 16 then
16 / 2 = 8
8 / 2 = 4
4 / 2 = 2
2 / 2 = 1
we divided successively 4 times and we reached 1, so the strongness of
16 is 4 Task
Given a closed interval [n, m], return the even number that is the
strongest in the interval. If multiple solutions exist return the
smallest strongest even number.
Note that programs must run within the alloted server time; a naive
solution will probably time out. Constraints
1 <= n < m <= INT_MAX Examples
for the input [1, 2] return 2 (1 has strongness 0, 2 has strongness 1)
for the input [5, 10] return 8 (5, 7, 9 have strongness 0; 6, 10 have
strongness 1; 8 has strongness 2)
for the input [48, 56] return 48
First I thought to store in a map each number as a key, and the number of times it is divisible by 2, as a value:
import java.util.*;
public class StrongestEvenNumber {
public static int strongestEven/*💪*/(int n, int m) {
System.out.println("n: "+n);
System.out.println("m: "+m);
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for(int i = n, number = 0, strongness = 0; i <= m; i++){
for(number = i, strongness = 0; number % 2 == 0; strongness++){
number /= 2;
}
map.put(i, strongness);
}
Map.Entry<Integer, Integer> maxEntry = null;
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
if(maxEntry == null || entry.getValue().compareTo(maxEntry.getValue()) > 0){
maxEntry = entry;
}
}
return maxEntry.getKey();
}
}
However, with large numbers, it runs out of heap memory space, or execution time runs out. For example with:
n: 1180381085
m: 2074186600
Java heap space runs out.
And with:
n: 324243
m: 897653214
Execution time runs out. The execution time exceeds 16000 ms
Then I tried to just store the number which is the most times divisible by 2:
import java.util.*;
public class StrongestEvenNumber {
public static int strongestEven/*💪*/(int n, int m) {
System.out.println("n: "+n);
System.out.println("m: "+m);
int maxStrongness = 0, maxNumber = 0;
for(int i = n, number = 0, strongness = 0; i <= m; i++){
for(number = i, strongness = 0; number % 2 == 0; strongness++){
number /= 2;
}
if(strongness > maxStrongness){
maxStrongness = strongness;
maxNumber = i;
}
}
return maxNumber;
}
}
Indeed it solves the heap space difficulty, however the execution time runs out behaviour stills happening.
For example with:
n: 200275492
m: 1590463313
The execution time exceeds 16000 ms
I have also read:
Finding Key associated with max Value in a Java Map
Get the key for the maximum value in a HashMap using Collections
https://math.stackexchange.com/questions/2589831/how-many-times-can-i-divide-a-number-by-another
Number of times all the numbers in an array are divisible by 2
optimize code to get the number of integers within given range that are divisible by integer
Well, the strongness of a value x is n when x is represented as
x = k * 2**n
knowing this we can check all powers of 2 (i.e. 1, 2, 4, 8, ...) if we can find any k such that
from <= k * 2**n <= to
Code:
private static int strongestEven(int from, int to) {
if (to < from)
return -1; // Or throw exception
// best power of 2 we can insert between [to..from] as k * best
int best = 1;
while (true) {
int ceiling = from / best + (from % best == 0 ? 0 : 1);
int floor = to / best;
if (ceiling > floor) {
best = best / 2;
return best * (to / best);
}
best *= 2;
}
}
Tests:
[ 1, 2] => 2
[ 5, 10] => 8
[48, 56] => 48
[80, 100] => 96
[97, 100] => 100
Finally,
[1180381085, 1590463313] => 1342177280
we have 1342177280 == 5 * 268435456 == 5 * 2**28 so the strongest number within [1180381085, 1590463313] range has strongness 28
Please, note, that the algorithm has O(log(to)) time complexity that's why will do even if we turn all int into long
The strongness is actually the number of trailing zeros in the binary representation of the number. You can use the java.lang.Integer.numberOfTrailingZeros to get it.
And as you want to test the even numbers, you can skipp the odd numbers in your loop.
public class StrongestEvenNumber {
public static int strongestEven(int n, int m) {
int maxStrongness = 0, maxNumber = 0;
for(int i = n%2==0?n:n+1, strongness = 0; i <= m; i=i+2){
strongness = Integer.numberOfTrailingZeros(i);
if(strongness > maxStrongness){
maxStrongness = strongness;
maxNumber = i;
}
}
return maxNumber;
}
This runs in the allocated time:
Completed in 13190ms
Input
1: array size (1 to 10^5)
2: Number to take average (1 to 10^3)
3: elements in array (1 to 10^5) Non sorted, any order is possible
Output: Maximum possible average of any sub-array.
Eg:
5 3
1 2 3 4 5
o/p = 5
5 4
1 2 3 4 5
o/p = 3
for first example seq will be sum[0,4]=15 and its average with 3 will be 5.
for second example seq will be sum[2,4]=12 and its average with 4 will be 3.
I already have below given solution of o(n^2) but its not working for large inputs.
long max = 0;
for( int m = 0; m < people; m++ )
{
long sum = 0;
for( int n = m; n < people; n++ )
{
sum = sum + chocolateArray[n];
if( sum % boxes == 0 )
{
if( ( sum / boxes ) > max )
{
max = sum / boxes;
}
}
}
}
System.out.println( max );
where people is array size, boxes is average number and chocolateArray is original array.
Please provide efficient solution. I thought to take it through dynamic programming but creating two dimensional array of 10^5 size is causing outofmemory issue.
Since all numbers are positive, the only effective constraint is the divisibility. So the question is asking for the maximum subarray sum that is divisible by m, the number of boxes.
This can be done by creating an array of the cumulative sum, modulo m, then finding two places with the same numbers, as far apart as possible. Since there are at most m values, we can simply store the minimum and maximum index of every possible residue, then take the one with the maximum subarray sum. The code below does that.
cumsum = int[people+1];
minPos = int[boxes];
maxPos = int[boxes];
Arrays.fill(minPos, -1);
Arrays.fill(maxPos, -1);
int residue = 0;
for(int i=0; i<people; i++){
cumsum[i+1] = cumsum[i] + chocolateArray[i]; // For simplicity the array length is 1 longer
residue = cumsum[i+1] % boxes;
if(minPos[residue] == -1) minPos[residue] = i;
maxPos[residue] = i;
}
int max = 0;
for(int i=0; i<boxes; i++){
int sum = cumsum[maxPos[i]+1] - cumsum[minPos[i]+1];
if(sum > max){
max = sum;
}
}
System.out.println(max/boxes);
For example:
People = 5
Boxes = 4
Array = [1, 2, 3, 4, 5]
Cumulative = [1, 3, 6, 10, 15]
Residue = [1, 3, 2, 2, 3]
MinMaxPos[0] = (-1, -1) -> sum = 0 -> avg = 0
MinMaxPos[1] = (0, 0) -> sum = 0 -> avg = 0
MinMaxPos[2] = (2, 3) -> sum = 4 -> avg = 1
MinMaxPos[3] = (1, 4) -> sum = 12 -> avg = 3
Building on #justhalf's brilliant solution. we will be able to do this using a single pass and only a single array
let dp[boxes] be a array of length boxes where dp[i] will hold the minimum sum so far which has i = current_sum % boxes
Since all the numbers are positive number we can store only the first occurrence of a the particular residue since the next time this residue occurs it will be greater that the previous sum.
At each iteration we check if a particular residue has been already found. If yes then then we subtract the current_sum with the previous sum of that residue.
Else we update the sum for the residue and move.
int maxSubArrayAverage(vector<int> people, int boxes)
{
vector<int> dp(boxes, -1);
int max_sum = 0, current_sum = 0;
dp[0] = 0; // if residue is 0 entire current_sum is the choice
for(int i=0; i < people.size(); ++i)
{
current_sum += people[i];
int residue = current_sum % boxes;
if(dp[residue] == -1) // update for the first time
{
dp[residue] = current_sum;
}
else
{
max_sum= max(max_sum, current_sum - dp[residue]);
// cout << i << ' ' << current_sum << ' ' << residue << ' ' << max_average << endl;
}
}
// copy(dp.begin(), dp.end(), ostream_iterator<int>(cout, " "));
// cout << endl;
return max_sum/boxes;
}
I just attempted a stack based problem on HackerRank
https://www.hackerrank.com/challenges/game-of-two-stacks
Alexa has two stacks of non-negative integers, stack A and stack B where index 0 denotes the top of the stack. Alexa challenges Nick to play the following game:
In each move, Nick can remove one integer from the top of either stack A or B stack.
Nick keeps a running sum of the integers he removes from the two stacks.
Nick is disqualified from the game if, at any point, his running sum becomes greater than some integer X given at the beginning of the game.
Nick's final score is the total number of integers he has removed from the two stacks.
find the maximum possible score Nick can achieve (i.e., the maximum number of integers he can remove without being disqualified) during each game and print it on a new line.
For each of the games, print an integer on a new line denoting the maximum possible score Nick can achieve without being disqualified.
Sample Input 0
1 -> Number of games
10 -> sum should not exceed 10
4 2 4 6 1 -> Stack A
2 1 8 5 -> Stack B
Sample Output
4
Below is my code I tried the greedy approach by taking the minimum element from the top of the stack & adding it to the sum. It works fine for some of the test cases but fails for rest like for the below input
1
67
19 9 8 13 1 7 18 0 19 19 10 5 15 19 0 0 16 12 5 10 - Stack A
11 17 1 18 14 12 9 18 14 3 4 13 4 12 6 5 12 16 5 11 16 8 16 3 7 8 3 3 0 1 13 4 10 7 14 - Stack B
My code is giving 5 but the correct solution is 6 the elements popped out in series are 19,9,8,11,17,1
First three elements from stack A & then from Stack B.
**
I don't understand the algorithm It appears like DP to me can anyone
help me with the approach/algorithm?
**
public class Default {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int numOfGames = Integer.parseInt(br.readLine());
for (int i = 0; i < numOfGames; i++) {
String[] tmp = br.readLine().split(" ");
int numOfElementsStackOne = Integer.parseInt(tmp[0]);
int numOfElementsStackTwo = Integer.parseInt(tmp[1]);
int limit = Integer.parseInt(tmp[2]);
int sum = 0;
int popCount = 0;
Stack<Integer> stackOne = new Stack<Integer>();
Stack<Integer> stackTwo = new Stack<Integer>();
String[] stOne = br.readLine().split(" ");
String[] stTwo = br.readLine().split(" ");
for (int k = numOfElementsStackOne - 1; k >= 0; k--) {
stackOne.push(Integer.parseInt(stOne[k]));
}
for (int j = numOfElementsStackTwo - 1; j >= 0; j--) {
stackTwo.push(Integer.parseInt(stTwo[j]));
}
while (sum <= limit) {
int pk1 = 0;
int pk2 = 0;
if (stackOne.isEmpty()) {
sum = sum + stackTwo.pop();
popCount++;
} else if (stackTwo.isEmpty()) {
sum = sum + stackOne.pop();
popCount++;
}
else if (!stackOne.isEmpty() && !stackTwo.isEmpty()) {
pk1 = stackOne.peek();
pk2 = stackTwo.peek();
if (pk1 <= pk2) {
sum = sum + stackOne.pop();
popCount++;
} else {
sum = sum + stackTwo.pop();
popCount++;
}
} else if(stackOne.isEmpty() && stackTwo.isEmpty()){
break;
}
}
int score = (popCount>0)?(popCount-1):0;
System.out.println(score);
}
}
}
Ok I will try to explain an algorithm which basically can solve this issue with O(n), you need to try coding it yourself.
I will explain it on the simple example and you can reflect it
1 -> Number of games
10 -> sum should not exceed 10
4 2 4 6 1 -> Stack A
2 1 8 5 -> Stack B
First you will need to creat 2 arrays, the array will contain the summation of all the number up to its index of the stack, for example for stack A you will have this array
4 6 10 16 17 //index 0 ->4
Same will be done for stack B
2 3 11 16
then for each array start iterating from the end of the array until you reach a number less than or equal to the "sum you should not exceed"
now your current sum is the sum of the point you reached in both arrays, should be 10 +3 = 13 so in order to reach 10 will absolutely need to remove more entries
to remove the additional entries we will be moving the indexes on the array again, to decide which array to move it's index take the entry you are pointing at (10 for array 1 and 3 for array 2) and device it by index+1 (10/3 ~ 3) , (3/2 ~1) then move the index for the highest value and recalculate the sum
Suppose we have:
a = 1 1 1 211 2
b = 1 85
and maxSum = 217
Now, on calculating prefix sums,
a' = 1 2 3 214 216
and b' = 1 86
current sum = 86+216 > 217
so to decide which index to remove, we compare `
216/5~43.2` and `86/2=43`,
so we move pointer in a'. BUT, that doesn't solve it - `
214+86 is still > 217!!`
Had we removed 86, it would've been better! So we should always go ahead by removing the one which has larger difference with previous element!
In case both values are equal its logical to move the index on the value which has larger difference with its previous ( remember we are moving the index in reverse order).
the result will be the sum of the indexes +2.
This solution works great.... i hope it helps ...
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int g = sc.nextInt();
for (int tc = 0; tc < g; tc++) {
int n = sc.nextInt();
int m = sc.nextInt();
int x = sc.nextInt();
int[] a = readArray(sc, n);
int[] b = readArray(sc, m);
System.out.println(solve(a, b, x));
}
sc.close();
}
static int[] readArray(Scanner sc, int size) {
int[] result = new int[size];
for (int i = 0; i < result.length; i++) {
result[i] = sc.nextInt();
}
return result;
}
static int solve(int[] a, int[] b, int x) {
int lengthB = 0;
int sum = 0;
while (lengthB < b.length && sum + b[lengthB] <= x) {
sum += b[lengthB];
lengthB++;
}
int maxScore = lengthB;
for (int lengthA = 1; lengthA <= a.length; lengthA++) {
sum += a[lengthA - 1];
while (sum > x && lengthB > 0) {
lengthB--;
sum -= b[lengthB];
}
if (sum > x) {
break;
}
maxScore = Math.max(maxScore, lengthA + lengthB);
}
return maxScore;
}
}
solution in python3
# stack implementation
class Stack:
lis = []
def __init__(self, l):
self.lis = l[::-1]
def push(self, data):
self.lis.append(data)
def peek(self):
return self.lis[-1]
def pop(self):
self.lis.pop()
def is_empty(self):
return len(self.lis) == 0
# number of test cases
tests = int(input())
for i in range(tests):
na, nb, x = map(int, input().split(' '))
a = list(map(int, input().split(' ')))
b = list(map(int, input().split(' ')))
temp = []
stk_a = Stack(a)
stk_b = Stack(b)
score = 0
count = 0
# first taking elements from stack A , till score becomes just less than desired total
for j in range(len(a)):
if score + stk_a.peek() <= x:
score += stk_a.peek()
count += 1
temp.append(stk_a.peek())
# storing the popped elements in temporary stack such that we can again remove them from score
# when we find better element in stack B
stk_a.pop()
# this is maximum number of moves using only stack A
max_now = count
# now iterating through stack B for element lets say k which on adding to total score should be less than desired
# or else we will remove each element of stack A from score till it becomes just less than desired total.
for k in range(len(b)):
score += stk_b.peek()
stk_b.pop()
count += 1
while score > x and count > 0 and len(temp) > 0:
count = count - 1
score = score - temp[-1]
temp.pop()
# if the score after adding element from stack B is greater than max_now then we have new set of moves which will also lead
# to just less than desired so we should pick maximum of both
if score <= x and count > max_now:
max_now = count
print(max_now)
I see that there exist a solution and you marked it as correct, but I have a simple solution
add all elements from stack one that satisfy condition <= x
every element you add push it on stack called elements_from_a
set counter to size of stack
try add elements from stack b if sum > x so remove last element you added you can get it from stack elements_from_a
increment bstack counter with each add , decrements from astack with each remove
compare sum of steps with count and adjust count return count
here is code sample for the solution :
def twoStacks(x, a, b):
sumx = 0
asteps = 0
bsteps = 0
elements = []
maxIndex = 0
while len(a) > 0 and sumx + a[0] <= x :
nextvalue = a.pop(0)
sumx+=nextvalue
asteps+=1
elements.append(nextvalue)
maxIndex = asteps
while len(b) > 0 and len(elements) > 0:
sumx += b.pop(0)
bsteps+=1
while sumx > x and len(elements) > 0 :
lastValue = elements.pop()
asteps-=1
sumx -= lastValue
if sumx <= x and bsteps + asteps > maxIndex :
maxIndex = bsteps + asteps
return maxIndex
I hope this is more simple solution.
void traversal(int &max, int x, std::vector<int> &a, int pos_a,
std::vector<int> &b, int pos_b) {
if (pos_a < a.size() and a[pos_a] <= x) {
max = std::max(pos_a + pos_b + 1, max);
traversal(max, x - a[pos_a], a, pos_a + 1, b, pos_b);
}
if (pos_b < b.size() and b[pos_b] <= x) {
max = std::max(pos_a + pos_b + 1, max);
traversal(max, x - b[pos_b], a, pos_a, b, pos_b + 1);
}
}
int twoStacks(int x, std::vector<int> &a, std::vector<int> &b) {
int max = 0;
traversal(max, x, a, 0, b, 0);
return max;
}
A recursion solution, easy to understand. This solution takes the 2 stacks as a directed graph and traversal it.
The Accepted Answer is Wrong. It fails for the below test case as depicted in the image.
For the test case given, if maximum sum should not exceed 10. Then correct answer is 5. But if we follow the approach by Amer Qarabsa, the answer would be 3. We can follow Geeky coder approach.
I have numbers as x,y,z, and w.
I am trying to create max possible time in 24 hours format.
Example:
My approach is to sort the all numbers. Then for hours check the number less than equal 2, then for next digit in hour, check number less then equal to 4,
and so on for minutes also. (0-60 minutes)
Is any other efficient approach than bruteforce solution?
Simple approach would be to create all possible combinations of all the number from four digits. Then sort and pick out all the values less than 2359 (Max time allowed). After this you start with the max number and just validate if it is a correct time if not check the next biggest number.
Basically what you can do is instead of all permutations you create conditions for each value in the array. For example if we have a 2 we know the hour should be 2 for our ten spot but our ones spot for the hour can only be 3 at that point. If we have a 1 then we know our one spot for the hour can be 9. We know our minute ten spot is 5 and our max minute one spot is 9. createTime shows these conditions. The findMaxSpecific returns -1 if it isn't able to find a valid number in the given array. That way we know the time is invalid if we ever get an array returned by createTime with -1's in it. See example output.
public static int[] createTime(int[] numbers)
{
int[] time = new int[4];
time[0] = findMaxSpecific(numbers, 2);
time[1] = time[0] == 2 ? findMaxSpecific(numbers, 3) : findMaxSpecific(numbers, 9);
time[2] = findMaxSpecific(numbers, 5);
time[3] = findMaxSpecific(numbers, 9);
return time;
}
public static int findMaxSpecific(int[] arr, int valToFind)
{
if(arr.length != 4)
return -1;
int numToFind = -1;
int indexToRemove = -1;
for(int i = 0; i < arr.length; i++)
{
if(arr[i] <= valToFind)
{
if(arr[i] > numToFind)
{
numToFind = arr[i];
indexToRemove = i;
}
}
}
if(indexToRemove == -1)
return -1;
arr[indexToRemove] = -1;
return numToFind;
}
At the end of all this is if any value comes back as -1 we know we have an invalid time we were given
Example
int[] time = new int[4];
int[] numbers = {1,2,3,4};
time = createTime(numbers);
System.out.println(time[0] + "" + time[1] + ":" + time[2] + "" + time[3]);
int[] numbers2 = {0,9,7,1};
time = new int[4];
time = createTime(numbers2);
System.out.println(time[0] + "" + time[1] + ":" + time[2] + "" + time[3]);
int[] numbers3 = {9,9,9,9};
time = new int[4];
time = createTime(numbers3);
System.out.println(time[0] + "" + time[1] + ":" + time[2] + "" + time[3]);
Output is
23:41
19:07
-19:-19 //invalid numbers
For input 1 2 9 9, the only possibility is 19:29, but what you describe picks the two first and gets 21:99, an invalid time.
Unless this is indeed a bottleneck and not a programming exercise, the most straightforward solution is to try all possible permutations of the digits, for each one, check whether it constitutes a valid time, and take the lexicographically maximal valid string.
The point is, there are fast solutions and there are correct solutions.
Here, the fast solution is tricky, so if program running time is not critical, do consider the possibility to pick the slower but more obvious solution.
This will perhaps give you, as a programmer, more time to tackle the other problems where running time does matter.
Sadly, Java does not seem to provide a builtin nextPermutation method, but Stackoverflow sure does.
input = (1,2,3,4)
ans = None
for hour in range(0, 24):
for minute in range(0,60):
if possible(hour, minute, input):
ans = "%s:%s" % (hour, minute)
here your possible function should count the digits in hour, minute and input and make sure they equate.
I would have a method you can give a predicate which extract the highest value which matches the predicate.
e.g.
public static int highest(List<Integer> values, Predicate<Integer> test) {
Integer max = values.stream()
.filter(test)
.max(Comparator.natrualOrder())
.orElseThrow(() -> new InvalidStateException());
values.remove(max);
return max;
}
int digit1 = highest(list, i -> i < 3);
int digit3 = highest(list, i -> i < 6);
int digit2 = highest(list, i -> digit1 < 2 || i < 4);
int digit4 = highest(list, i -> true);
Interesting problem. Seems a little bit more complex than it appears. Here is a python script for the problem.
def getmin(num): # check if two digits are valid for minutes
min = -1
sum = num[0] * 10 + num[1]
if sum < 60:
min = sum
sum = num[1] * 10 + num[0]
if sum < 60 and min < sum:
min = sum
return min
def maxtime(num):
hour = -1
min = -1
h1 = 0
h2 = 0
for i in range(4):
for j in range(4): # these two loops are to get maxi hour, if possible
if i != j:
sum = num[i] * 10 + num[j]
if hour < sum and sum < 24:
c = num[:] # get a copy of input digits
if i > j: # delete numbers used in hour
del c[i]
del c[j]
else:
del c[j]
del c[i]
if getmin(c) > -1:
h1 = i
h2 = j
hour = sum
if hour > -1:
if h2 > h1: # delete numbers used in hour
del num[h2]
del num[h1]
else:
del num[h1]
del num[h2]
min = getmin(num)
if min > -1:
print(str(hour) + ':' + str(min))
if hour < 0 or min < 0:
print("no solution")
maxtime([4, 8, 1, 9])
maxtime([7, 3, 4, 2])
maxtime([9, 2, 2, 5])
maxtime([9, 2, 7, 3])
#19:48
#23:47
#22:59
#no solution
I have a programming competition coming up and I am solving last years problems as revision for the competition, i came across a simple program however it requires math which unfortunately i am very bad at.
Here is the question:
Given a positive integer n,find the odd integer o and the
non-negative integer p such that n=o2^p (o multiplied by 2
to the power p)
the first line of the input file contains exactly one positive integer
d equal to the number of test cases,1<=d<=10. the data set follows. Each data set consists of exactly one line containing
exactly one integer n, 1<=n<=10^6
Sample output
2 //d value of number of test cases
24 // value of n
27 // value of n
Sample output
3 3 // first 3 is value of o, 2nd 3 is value of p
7 7 // first 7 is value of o, 2nd 7 is value of p
the "//" part should not be in the output or input
and this is what I have done so far, I got everything right except for the formula I need to use for the equation to solve correctly
public static void main(String[] args) {
double n = 0, d = 0, o = 0, p = 0;
double x = 1;
//START INPUT
Scanner input = new Scanner(System.in);
//input d, number of times program repeats
System.out.println("Please enter the number of times you want to run the test(no more than 10)");
d = input.nextDouble();
//check the validity of d
while((d > 10) || (d<1)){
System.out.println("Invalid input");
System.out.println("Enter another value for d");
d = input.nextDouble();
}
while(x <= d){
x++;
System.out.println("enter a value for n");
n = input.nextDouble();
//check the validity of n
while((n > 1000000) || (n<1)){
System.out.println("Invalid input.");
System.out.println("Enter Another Value for n");
n = input.nextDouble();
}
//Calculates
p = Math.log(n) / Math.log(2.0);
o = n / Math.pow(p, 2);
//STOP CALCULATE
//PRINTS
System.out.println(o + " " + p);
}
}
Any help is appreciated.
All you need to do is repeatedly divide by 2:
function removeTwo(n)
o, p := n, 0
while o % 2 == 0
o, p := o/2, p+1
return o, p
I'll leave it to you to translate to Java.
Many different ways. For programming contests I usually go with a simple approach when there are small numbers: bruteforce! Maybe not a perfect answer to your question, but keep it in mind when doing other tasks at the competition: working is good enough, choose the first solution you can come up with and try implementing it. At least that's true for most competitions I've been at, where it's about doing as many tasks as possible within a given time frame.
For the formula n = o2p,
with o odd and p > 0, and 1 <= n <= 106,
we can see that 2p will always be at least 2.
That means that o should be below half of n, so we only need to search for o's up to half of the value we're given. And we only need to check odd values.
And then one can just try different p values for the chosen o. If the result is higher than n, we should try the next value of o.
javacode:
public void calc(int n) {
for (int o = 1; o <= n / 2; o += 2) {
int p = 1;
while (true) {
int test = o * (int) Math.pow(2, p);
if (test == n) { // solution found
System.out.println("o:" + o + ", p:" + p);
return;
}
if (test > n) break; // total value too high, lets start with another o
p++;
}
}
}
Stepping through this with you input of n=24:
o = 1, p = 1 => 2
o = 1, p = 2 => 4
o = 1, p = 3 => 8
o = 1, p = 4 => 16
o = 1, p = 5 => 32, too high, try another o
o = 3, p = 1 => 6
o = 3, p = 2 => 12
o = 3, p = 3 => 24, TADA!
Different bruteforce methods may be to instead start with the value of p, or to instead divide n by different values of 2p until you get an odd integer.
The problem actually does not involve sooo much math. It's rather about bit twiddling.
It helps to know that each value 2^p is equal to (1<<p). Knowing this, you can first compute the highest bit that is set in n. For example
n = 24 = 11000 (binary) : Highest bit is 4
n = 36 : 100100 (binary) : Highest bit is 5
Then you can start with this bit position as a candiate for p, decrease this value until you find that the equation is solvable. When you reach zero, then the input value n must have been odd. This could be detected explicitly at the beginning, if desired.
import java.util.Arrays;
public class FindFactors
{
public static void main(String[] args)
{
for (int n=0; n<100; n++)
{
System.out.println("For "+n+" : "+Arrays.toString(findFactors(n)));
}
}
private static int[] findFactors(int n)
{
int p = highestBit(n);
while (p >= 0)
{
int twoPowP = (1 << p);
int c = n / twoPowP;
if (c * twoPowP == n)
{
return new int[]{c,p};
}
p--;
}
return null;
}
private static int highestBit(int n)
{
int b = 0;
while (n > 1)
{
n >>= 1;
b++;
}
return b;
}
}