Multiply by two then every three years by three - java

I am working on an assignment that asks:
Magic Plant
We have a magic plant that once it is planted, it germinates and grows two leaves in the first
year. It doubles its leaves every year except that every three years it triples its leaves.
Something like:
Year: 1 | 2 | 3 | 4| 5| 6 | 7 …
Leaves: 2 | 4 | 12| 24| 48|144|288 …
What I have completed so far:
int n = 0;
int l = 6;
for(int i = 2; i>-1; i++) {
if(i == l) {
break;
}
if(i != l) {
n = 2 * i;
}
if(i == l) {
break;
}
if(i != l) {
n = 3 * i;
}
System.out.println(n);
}
My thought process behind that was to check if it passed the year 6 before it multiplied it by two and then by three on the third year, then repeat.
This does not work the output is:
3
6
9
15
I need to be able to input a year and find a number of leaves,
as well as take the number of leaves and find out how old the plant is.

public static void main(String [] args)
{
String years = "";
String leave = "";
int num_years = 10;
int leave_count = 1;
for(int i=1;i<= num_years;i++) {
leave_count = (i%3 == 0)? leave_count * 3:leave_count*2;
years = years + i +"|";
leave = leave + leave_count + "|";
}
System.out.println(years+"\n"+leave);
}

how about this:
int years = 30; //number of years
long leaves = 0; //long is better because int will overflow faster
for(int i = 0 ; i < years ; ++i){
if(i == 0)//first year
leaves += 2;//adds 2 leaves
else if(i % 3 == 0) //Every third year
leaves *= 3; //triple leaves
else//every other year
leaves *= 2; //doubles leaves
System.out.println(leaves);
}
will print:
2
4
8
24
48
96
288
576
...
Test the code here
You could use the mod or remainder operator (%), it's pretty handy for this kind of tasks.
I recommend using better names for your variables since it can be detrimental in the long run; use self explanatory names like numberOfLeaves instead of n and sixthYear instead of l.
Using this knowledge you could get the number of years of the tree, since it's an assignment (for collegue I guess...) I'll not put the code for that but I will give you a hint of a way to do it: substract inside a loop until you have zero leaves.

Here is a recursive way to do it.
private static int[] numberOfLeaves(int year) {
if (year > 1) {
if (year % 3 != 0) {
int[] ret1 = new int[2];
ret1[0] = ++numberOfLeaves(year - 1)[0];
ret1[1] = numberOfLeaves(year - 1)[1] * 2;
return ret1;
} else {
int[] ret2 = new int[2];
ret2[0] = ++numberOfLeaves(year - 1)[0];
ret2[1] = numberOfLeaves(year - 1)[1] * 3;
return ret2;
}
}
int[] ret = new int[2];
ret[0] = year;
ret[1] = year * 2;
return ret;
}
It is tested. When you print out the data, you should access it by index (ret[0] for number of years and ret[1] for number of leaves.).

Related

Why does my output give me the wrong amount of each number?

I am trying to make a program where I can input the size of a 2D array, the highest number in a 2D array, and the most amount of a certain number in the 2D array, and then fill it with random numbers in between 1 and the highest number. In my code, I specify that the max amount of times a number should repeat is 4, yet my output doesn't match that. Any suggestions?
This is my code:
class Main {
public static void main(String[] args) {
System.out.println(fill(6, 9, 4));
}
public static String fill(int size, int max, int most) {
int[][] list = new int[size][size];
int count = 0;
for (int i = 0; i < list.length; i++) {
for (int j = 0; j < list[i].length; j++) {
int x = (int)((Math.random()* max) + 1);
int y = 0;
count = 0;
for (int k = 0; k < list.length; k++) {
for (int l = 0; l < list[k].length; l++) {
if(list[k][l] == x) count++;
}
}
if(count < most) {
list[i][j] = x;
} else {
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
list[i][j] = y;
}
System.out.print(list[i][j] + " ");
}
System.out.println();
}
return "";
}
}
And this is my output:
9 4 6 1 9 1
7 1 4 4 3 2
6 1 4 2 7 9
5 9 4 7 2 5
3 5 3 5 7 4
3 8 8 6 2 6
Problem: There are 6 "4"s and 2 "8"s
You generate a random number.
You then check if this random number is 'invalid', in the sense that it's been used too many times.
Then, you generate a new random number, check that this isn't the same as your previous number, and then just roll with that. You are failing to check if this number, too, is 'overloaded'. So, what could have happened here is that your algorithm picked '9', counts 9s, finds 4 of them, rolls up a new random number, 9 again, so it rolls yet another number, 4, and just puts 4 in, without checking again.
Rejigger your while loops.
Or, better yet, make a utility class to offload the job of generating a random number, but not a number that's already been returned N times, to a separate class, so that you can untangle this messy code.
Your method
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
does not check that count of y did not already reached most
Your Issue is here:
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
list[i][j] = y;
This basically just rules out that x will be repeated more than most, but not y.
On a side note, I recommend using hash maps to keep track of the occurrences instead of iterating over the whole array over and over.

what is the best algorithm to solve this programming challenge ? Given a positive integer number consisting only of digits 6 and 9 [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Given a positive integer num consisting only of digits 6 and 9.
Return the maximum number you can get by changing at most one digit (6 becomes 9, and 9 becomes 6).
Example 1:
Input: num = 9669
Output: 9969
Explanation:
Changing the first digit results in 6669.
Changing the second digit results in 9969.
Changing the third digit results in 9699.
Changing the fourth digit results in 9666.
The maximum number is 9969.
Example 2:
Input: num = 9996
Output: 9999
Explanation: Changing the last digit 6 to 9 results in the maximum number.
Example 3:
Input: num = 9999
Output: 9999
Explanation: It is better not to apply any change.
Traverse from left to right and change the first occurrence of 6 to 9. If there is not any 6 while traversal then does not change any digit.
Following code may help:-
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class testing {
public static void main(String[] args) throws FileNotFoundException {
Scanner sc=new Scanner(System.in);
System.out.print("Enter a number : ");
int a=sc.nextInt();
String numberString = Integer.toString(a);
for (int i = 0; i < numberString.length(); i++){
char c = numberString.charAt(i);
if(c=='6') { // check if the digit is 6 or not, if 6 is present then change it to 9
numberString = numberString.substring(0, i) + '9' + numberString.substring(i + 1);
break; // break the loop if 6 is changed to 9
}
}
System.out.println("Largest Number is : "+numberString);
}
}
public class Maximum69 {
public static void main(String[] args) {
int num=6669;
int added = 0;
int cur = 1;
int curNum = num;
while(curNum > 0) {
if(curNum % 10 == 6)
added = cur;
cur *= 10;
curNum = curNum / 10;
}
System.out.println(num + added * 3);
}
}
I found out how to slove, This takes less time to run:
I have found a formule, it could have been a single line solution but for clarity I have divided in two lines
First , get the highest number based on input number of digits , for example if input is 6, topNumber will be 9, for 69 top will be 99 , for 696 top is 999, so topNumber can be 9 or 99 or 999 or 9999 or 99999,etc up to java limit, the formula to get number of digits in an integer is :
floor(log10(input)) + 1
Then you can notice that the top number minus the input, it gives you a number that starts with 3, for example 9-6 = 3 , 99 - 69 = 30 , 999 - 696 = 303, except when the input is equal to the top number, in that case the result is 0,
knowing that fact, we can conclude that for switching the first 6 in the number can be achieved by summing up 3 * (((the position of the 6) -1) * 10) , eg. 3 or 30 or 300 or 3000 or 30000, etc.
resulting in the last part of the function : input + (10^(NumberOfDigits(top - input)) -1) * 3
private static int largest69(int number) {
int topNumber = (int) (Math.pow(10,(int)(Math.log10(number)) + 1) -1);
return number + (int) Math.pow(10,(( (int)(Math.log10(topNumber - number)) + 1 ) -1) ) * 3;
}
If you're not as good as nitinsridar at intuitively implementing math into your algorithm, and if you don't want to mess around with strings like backdoor did, then you can utilize data structures to help you come to a solution without much thought
public static void main(String[] args) {
System.out.println(maxNumber(9669));
}
public static int maxNumber(int number) {
Stack<Integer> numbers = new Stack<Integer>();
int numberLength = 0;
while(number > 0) {
numbers.push(number % 10);
number /= 10;
numberLength++;
}
boolean changedFirstOccurrence = false;
int maxNumber = 0;
for(int i = numberLength; i > 0; i--) {
int numberToAdd = numbers.pop();
if (numberToAdd == 6 && !changedFirstOccurrence) {
numberToAdd = 9;
changedFirstOccurrence = true;
}
maxNumber += numberToAdd * (int) Math.pow(10, i);
}
return maxNumber / 10;
}
Is this the best solution? Nope, I would go with nitinsridar's answer (I also believe that his/her answer should get the green checkmark).
Backdoor's answer is definitely how I would've solved this problem before I took my data structures and algorithms class. I'm not saying it's a bad answer. In fact, his algorithm is more concise than mine. It's just my opinion that you don't want to get in the habit of relying on string manipulation to solve these sort of "numerical" problems, because one day it's not going to work; in this case, it did. I'm just providing another way of doing it

Java - numbers with at least one 7 and one 9 in its digit

I have to code a program to determine how many positive integers under 1,000,000 have at least one 7 and at least one 9 among its digits by examining the digits in each number from 1 to 999,999 ("brute-force" method). The answer is supposed to be 199,262. Please help!
How about converting the number to a String and text if it contains 7 and 9
int count = 0;
for (int i = 1; i < 1000000; i++) {
String text = String.valueOf(i);
// contains both
if (text.contains("7") && text.contains("9")) count++;
}
System.out.println(count);
Some combinatorics for you:
Number of two digit numbers without a 7 (or without a 9):
8*(9^1) = 72
Number of 2-digit numbers without a 9 or 7:
7*(8^1) = 56
Number of 2-digit numbers:
9*(10^1) = 90
Number of 2-digit numbers with at least one 7 and one 9:
90 - 2*72 + 56 = 2
Formula for n-digit calculation:
= 9*(10^(d-1)) - 2*8*(9^(d-1)) + 7*(8^(d-1))
9*(10^1+10^2+10^3+10^4+10^5)
- 2*8*(9^1+9^2+9^3+9^4+9^5)
+ 7*(8^1+8^2+8^3+8^4+8^5)
= 199262
The brute force algorithm:
public int count() {
int count = 0;
boolean per7 = false;
boolean per9 = false;
for (int i = 0; i < 1000000; i++) {
int j = i;
while ((!(per7 && per9)) && j > 1) {
if (j%10 == 7) {
per7 = true;
} if (j%10 == 9) {
per9 = true;
}
j = j/10;
}
if (per7 && per9) {
count++;
}
per7 = false;
per9 = false;
}
return count;
}
On the other hand, I would suggest using basic knowledge about combinatorics, but I understand that during studies, we often do stupid tasks to learn certain skill.

Looking for an iterative solution of a recursive one

For the following question I implemented both recursive and recursive dynamic solution, however I am interested in an iterative solution ( not recursive). Can anyone help me with that?
Question:
A cat is jumping up a staircase with n steps, and can hop either 1 step, 2 steps, or 3 steps at a
time. Implement a method to count how many possible ways the cat can jump up the stairs.
For iterative solution what I know is that we essentially have to count the leaves of the trinary tree below with value 0
Dynamic and recursive solutions:
import java.util.ArrayList;
public class Question1 {
public static int countAndDisply(int n, ArrayList<Integer> hop) {
if (n<0){
return 0;
}else{
if (n==0) {
for(int i:hop){
System.out.print(i+",");
}
System.out.println();
return 1;
}else{
ArrayList<Integer> hop1 = new ArrayList<>(hop);
hop1.add(1);
ArrayList<Integer> hop2 = new ArrayList<>(hop);
hop2.add(2);
ArrayList<Integer> hop3 = new ArrayList<>(hop);
hop3.add(3);
return countAndDisply(n-1, hop1)+countAndDisply(n-2, hop2)+countAndDisply(n-3, hop3);
}
}
}
/**
* Faster by using dynamic programming techniques to improve speed
* We dont want to calculate the count(n) multiple times!
* #param n
* #param path
* #return
*/
public static int countFast(int n, int[] map){
if (n<0){
return 0;
}else{
if (n==0) {
return 1;
}else{
if (map[n]>0){
return map[n];
}else {
return countFast(n-1, map) + countFast(n-2, map) + countFast(n-3, map);
}
}
}
}
public static int count(int n){
if (n<0){
return 0;
}else{
if (n==0) {
return 1;
}else{
return count(n-1) + count(n-2) + count(n-3);
}
}
}
public static void main(String[] args) {
int n=10;
int [] map = new int[n+1];
long startTime = System.nanoTime();
System.out.println("Total number of possiblilities:"+Question1.countFast(n,map));
long totalTime = System.nanoTime()-startTime;
System.out.println("Time needed for dynamic recursive approach was(ns):"+totalTime);
//System.out.println("Total number of possiblilities:"+Question1.AndDisply(n,new ArrayList<Integer>()));
System.out.println("Total number of possiblilities:"+Question1.count(n));
totalTime = System.nanoTime()-startTime;
System.out.println("Time needed for pure recursive was(ns):"+totalTime);
}
}
and here are outputs:
Total number of possiblilities:274
Time needed for dynamic recursive approach was(ns):249311
Total number of possiblilities:274
Time needed for pure recursive was(ns):351088
If you want to do it iterative, the best way is to start from 0, not from n.
An example:
i i-1 i-2 i-3 sum
0 || -1 -2 -3 | 0 # does not contain any solution
1 || 0 -1 -2 | 1 # contains one solution (0)
2 || 1 0 -1 | 2 # contains two solutions (0,1) - (-1,-2)
3 || 2 1 0 | 4 # contains three solutions(0,1,2)
# 2 (2) ,1(1) +1 (0) => 2+1+1 = 4
4 || 3 2 1 | 7 # 3 (4) ,2(2) 1 (1) => 4+2+1 = 7
5 || 4 3 2 | 13 # and so on
6 || 5 4 3 | 24
7 || 6 5 4 | 44
8 || 7 6 5 | 81
9 || 8 7 6 | 149
10 || 9 8 7 | 274
The code is extremely simple:
public static int solve(int n) {
int[] map=new int[n+1];
map[0]=1;
map[1]=1;
map[2]=2;
for (int i = 3; i < map.length; i++) {
map[i]+=map[i-1];
map[i]+=map[i-2];
map[i]+=map[i-3];
}
return map[n];
}
And much faster, of course.

How to "invert" numbers in Java

Lets say I have a number 1-5, now if I have 2, I want 4 as an output, if I had 3 then have 3 as the output, if I have 1 then 4 as the output. Here is a chart of what I want:
1-10 Chart:
Give 1 return 9
Give 2 return 8
Give 3 return 7
Give 4 return 6
Give 5 return 5
What algorithm do I use for such a thing?
I don't see that you need an algorithm as much. What you have is:
InverseNumber = (myCollection.Length - MySelection);
Thats all you need for even numbers.
With a collection of 1 - 6 for example:
Give 2; 6 - 2 = 4. Also if given 4, 6 - 4 = 2.
You will need a slightly different problem for odds:
1 - 5; with 1 given 1 is at index 0, the opposite is 5, 2 given and the inverse ( 5 - 2) is 3. But if 3 is given, there is no inverse. So you might want to also add a catch for:
if (((myCollection.Length *.5).Round) == mySelection) { //Inverse does not exist!!!}
If you are using just integers, and not arrays of numbers then just replace the myCollection.Length with the upperbound integer.
I think the following code will work for what you need:
int a[] = new a[length_needed];
int counter = length_needed;
for(int c = 0; c < length_needed; c++) {
a[c] = counter;
counter--;
}
int number_inputed;
for(int c = 0; c < length needed; c++) {
if(c == number_inputed) System.out.println(a[c]);
}
Let's say you are giving max number as input. Then you are going to have 0-n numbers. For ex., if 9 is the max number you will have 0-9.
Then you can do something like this:
public static void main(String[] a) {
int max = a[0]; // read values from cmd line args
int forWhichNum = a[1]; //for which number we need its inverse
Sop(max- forWhichNum);
}
Integer value = 2;
Integer maxValue = 6;
Integer reverseCounter = 0;
for (int i = maxValue; i > 0; i--) {
reverseCounter++;
if (i == value) {
return reverseCounter;
}
}

Categories

Resources