Returns a string consisting of a Hailstone sequence beginning with the positive integer n and ending with 1. The
string should consist of a sequence of numerals, with each numeral followed by a single space. When a numeral m
(other than 1) appears in the sequence, it should be followed by nextHailstone(m).
Examples: nextHailstone(1) is "1 " and nextHailstone(5) is "5 16 8 4 2 1 ".
public static String hailstones (int n)
{
int calculation = 1;
System.out.print(n + " ");
while (n > 1)
{
if (n % 2 == 0)
{
n /= 2;
}
else
{
n = (n*3) + 1;
}
calculation++;
System.out.print(n + " ");
}
return " ";
}
The code works fine when I call the method in the main method but the test case for it is failing.
#Test
public void testHailstones ()
{
assertEquals("1 ", hailstones(1));
assertEquals("16 8 4 2 1 ", hailstones(16));
assertEquals("7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 ", hailstones(7));
}
Those are the test cases. any insight into this would be great. thanks!
You return " " every time the function is called. You need to build up an internal string and return that as result.
Related
I have a main function that calls another function and passes the given number as a parameter. In the other function, I want to break up the given number into sums of power. How can this be done?
My code looks like:
public static void main()
{
String hello=raisetopower(in.nextInt());
}
public String raisetopower(int n)
{
// do the logic
}
Explanation :
say if the number is 25: the function should return 5^2 + 0^2
and if it is 26: 5^2+1^2
I agree with Richard's comment that this more Mathematics than Java
The question needs more information to be able to provide code to assist, such as whether or not you consider a maximum base like 10 and whether or not all bases should be in the output even if they are to the power of 0 as your example is confusing:
"say if the number is 25: the function should return 5^2 + 0^2 and if
it is 26: 5^2+1^2"
However with that in mind, hopefully this example will be able to assist
Assuming you do have a maximum base being considered, you could start from the highest base to the lowest and use logs
If the result of the log is greater than or equal to 1, then this value should be in the output, so subtract that value and continue on to the next base
Keep continuing until you hit a value of exactly 1 and that should be your end condition
E.g assuming a maximum base of 5 for this example with an input of 27
log5 27 = 2.04781858346
so we will have 5^2 in the output and subtract this from the input, you could use floor to extract the '2'
log4 2 = 0.5
less than one so not an integer power
log3 2 = 0.630929753571
less than one so not an integer power
log2 2 = 1
add to output as greater than or equal to 1 and terminate as it is exactly 1
If you're only displaying bases with powers greater than or equal to one (this was unclear), your output at this point would be:
27 = 25^2 + 2^1
You could use a StringBuilder or an ordered collection of custom objects holding your bases and powers to make it easier to generate the output
Here's an SSCCE for my above algorithm:
import java.util.Scanner;
public class NumberToPowerConversion {
public static void main(String[] args) {
int maxBaseToConsider = 5;
System.out.println("Input number to convert: ");
Scanner input = new Scanner(System.in);
int number = input.nextInt();
StringBuilder output = new StringBuilder("Represented as powers: " + number + " = ");
for(int base = maxBaseToConsider; base >= 1; base--){
//Prevent division by 0 (log 1)
double logResult = base > 1 ? Math.log(number) / Math.log(base) : 1;
int floorResult = (int)Math.floor(logResult);
if(number == 1 || logResult == 1.0){
output.append(base + "^" + floorResult);
number -= Math.pow(base, floorResult);
if(number != 0){
//If the number couldn't be broken down completely, add the remainder to the output
output.append(" + " + number + "^1"); //To keep format consistent
}
break; //end condition reached
}
else if(floorResult >= 1){
output.append(base + "^" + floorResult);
number -= Math.pow(base, floorResult);
if(number == 0){ break; }
else{ output.append(" + "); }
}
}
System.out.println(output.toString());
}
}
Example output:
Represented as powers: 27 = 5^2 + 2^1
Represented as powers: 77 = 5^2 + 4^2 + 3^3 + 2^3 + 1^1
Represented as powers: 234 = 5^3 + 4^3 + 3^3 + 2^4 + 1^1 + 1^1
Represented as powers: 99 = 5^2 + 4^3 + 3^2 + 2^0
Represented as powers: 1 = 5^0
I have actually found the solution of this problem over here : https://github.com/Widea/Interview-Questions/blob/master/Hard/Random/PowerNumbers.java
/* Algorithm :
i <- square root of n
while n<1
n <- n-square of i
r <- r concatenate with i^2
if n=0 r concatenate with i^0
if n=1 r concatenate with i^1
i <- square root of n
return r
*/
public static String raisetopower(int n){
String raised="";
int i=(int)Math.sqrt(n);
while(n>1){
n=n-(int)Math.pow(i,2);
raised+=String.valueOf(i)+"^2+";
if(n==0)
raised+="0^2";
if(n==1)
raised+="1^2";
i=(int)Math.sqrt(n);
}
return raised;
}
i write this code and i try to understand all activities performed (recursive).
Can anyone help me with this draw me up a tree in memory of what happens?
public static String row(int n) {
if (n == 1)
return "1";
else
return row(n - 1) + " " + n;
}
public static String triangle(int a, int b) {
if (a == b)
return row(b);
else
return row(a) + "\n" + triangle(a + 1, b);
}
}
thank's
Your row method:
public static String row(int n) {
if (n == 1) {
return "1";
} else {
return row(n - 1) + " " + n;
}
}
Returns a String containing all the numbers from 1 - n separated by spaces. E.g.row(4) will return a string "1 2 3 4".
Your triangle method prints one row for each row of a triangle.
public static String triangle(int a, int b) {
if (a == b) {
return row(b);
} else {
return row(a) + "\n" + triangle(a + 1, b);
}
}
creates one row of a triangle for each step of row from a up to b.
e.g. triangle(4,6) will print:
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
How the code works
The row method, if given the value 1 will return "1". Any other value will result in a string equivalent to row(n-1) followed by n so essentially it will return 1 2 3 ... n.
The triangle method returns a string which attempts to draw a triangle with numbers. Thus triangle(4,6) returns row(4) + triangle(5,6) which returns row(5) + triangle(6,6) which will returns row(6). Thus the final result will be:
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
I have to find sum of the all even numbers that are not divisible by 7 using recursion. I tried this code but it seems I am making mistake somewhere because it returns 0:
public static void main(String[] args) {
System.out.println(specialSum(50));
}
public static int specialSum(int a) {
if ((a >= 1) && ((specialSum(a-1))%7 !=0)) {
return a + specialSum(a -1);
} else{
return 0;
}
}
}
Instead of if ((a >= 1) && ((specialSum(a-1))%7 !=0)) try if ((a >= 1) && (a%7) !=0)), as it is now, you're never checking if the original a value is not divisible by 7, your first check is always a - 1.
In recursion, you just need to focus on current step, you shouldn't user specialSum(a -1) in a condition. This is the next step, you should only call it after focusing on the current step.
You should just apply your two rules to succeed : add the current number to the nexts only
- if they are even
- if they are not divisible by 7.
public static int specialSum(int a) {
if(a <= 1) // Final Case.
{
System.out.print(" 0 = ");
return 0;
}
if(a%2 != 0) // Even Number, do not sum, call next step
{
return specialSum(a-1);
}
else
{
if(a % 7 == 0){ // Divisible by 7 Do not sum, call next step.
return specialSum(a-1);
}
else // NOT divisible by 7 nor by 2, add it to the next step
{
System.out.print(a+ " + ");
return a + specialSum(a-1);
}
}
}
outputs :
50 + 48 + 46 + 44 + 40 + 38 + 36 + 34 + 32 + 30 + 26 + 24 + 22 + 20 + 18 + 16 + 12 + 10 + 8 + 6 + 4 + 2 + 0 = 566
Here you have the solution in one line, you should have a case to stop the recursion, in your case you stop the recursion at 49 because it is divisible by 7, and you don't take into account numbers less than 49
main()
{
specialSum(50, 7);
}
public static int specialSum(int a, int toDivide)
{
return (a == 0) ? 0 : (a >= 1 && a%2 == 0 && a%7 != 0) ? a + specialSum(a - 1, toDivide) : specialSum(a - 1, toDivide);
}
This works for me. The first if makes sure to only take even numbers. Then second if makes sure only to sum if not divisible by 7. The last if sums the result.
public static void main(String[] args) {
System.out.println(specialSum(50, 0));
}
public static int specialSum(int max, int current){
if(max % 2 == 1)
max -= 1;
if(max % 7 != 0)
current += max;
if(max >= 1){
max -= 2;
return specialSum(max, current);
}
return current;
}
This returns 566.
Equal to: 50 + 48 + 46 + 44 + 40 + 38 + 36 + 34 + 32 + 30 + 26 + 24 + 22 + 20 + 18 + 16 + 12 + 10 + 8 + 6 + 4 + 2.
public static int specialSum(int a) {
if ( a % 7 !=0 && a%2==0 ) {
return a + specialSum(a - 2);
} else {
if (a > 2 ) {
a=a-2;
return a + specialSum(a - 2);
} else {
return 0;
}
}
}
Your code is wrong.
The condition (specialSum(a-1))%7 !=0) in your code calls the method for 49, when a=50. This calls the method for 48, which calls for 47 and so on until a=1. Then, it calls for 0, which is not greater than or equal to 1, and hence it returns 0. Now, 0%n for any number, is 0. Hence, you get 0 as the output.
Change your method to something like this:
public static int specialSum(int a) {
if(a<=2) return 2; // base case
else if(a%7==0) return specialSum(a-2); // if it is divisible by 7, then do not add it, and call the method for a-2.
else return a+specialSum(a-2); // else add the number, and get the answer for a-2.
}
You need to check if a is divisible by 7, so you should use if ((a>=1) && (a%7) !=0)) to make sure that the you check for the base condition.
I'm writing a program where you input two divisors and a list of numbers you want to check are divisible by the two numbers you inputed.
Here's an example of how the output should look like:
Please input a command: A
A [Create a new divisible test]
[Type two divisors]: 2 6
[Input a list of numbers in one single line]: 2 4 6 9 15 18 19 25 30
Please input a command: D
D [Display the information]
( 2 4 6 9 15 18 19 25 30 ) are numbers to check
( 2 4 6 18 30 ): are divisible by 2
( 6 18 30 ): are divisible by 6
( 6 18 30 ): are divisible by both 2 and 6
My problem is it won't check which number is divisible by the two divisors, instead it prints out
( 2 4 6 9 15 18 19 25 30 ) are numbers to check
( 2 4 6 9 15 18 19 25 30 ): are divisible by 2
( 2 4 6 9 15 18 19 25 30 ): are divisible by 6
( 2 4 6 9 15 18 19 25 30 ): are divisible by both 2 and 6.
here's my code:
class Divisible {
private int divisor1;
private int divisor2;
public String numbers;
public Divisible() {
divisor1 = (Integer) null;
divisor2 = (Integer) null;
numbers = " ";
}
public Divisible(int div1, int div2, String num) {
this.divisor1 = div1;
this.divisor2 = div2;
this.numbers = num;
}
private boolean isDivisible1(int input) {
boolean isDivisible1 = true;
return (input % divisor1 == 0);
}
private boolean isDivisible2(int input) {
boolean isDivisible2 = true;
return (input % divisor2 == 0);
}
public String printDivisible1() {
if (this.isDivisible1(divisor1)) {
System.out.println();
System.out.println("are divisible by " + divisor1);
}
return numbers;
}
public String printDivisible2() {
if (this.isDivisible2(divisor2)) {
System.out.println(" are divisible by " + divisor2);
}
return numbers;
}
public String printDivisibleBoth() {
if (this.isDivisible1(divisor1) && this.isDivisible2(divisor2))
System.out.println(" are divisible by " + divisor1 + " and " + divisor2);
return numbers;
}
}
It looks to me like you're missing a few steps in your code!
To solve this problem we need to:
Break the string of numbers up, and convert them into integers, and enter them into a list or array.
Iterate over this list when printing, applying your isDivisible() function to determine if it should go to output.
First I think maybe we could make your program a bit more modular. In particular your isDivisible(int input) functions could be changed to something like:
private boolean isDivisible(int input, int divisor) {
return (input%divisor==0);
}
this means we can use the same function for both our divisors! Like isDivisble(30, 6) and isDivisble(30, 2)
Now we need to focus on your string of numbers to check. You'll notice our new function requires an integer for the input, but we currently have a huge string containing all our numbers. We could probably try a function like:
String[] numArray = num.split(" ");
to take our String 'num' and split it up into pieces wherever there is a space (" "), and put those pieces into the elements of the 'numArray' array.
Ok, now we have our array of inputs. All that's left is to convert these elements into Integers so they can be used as inputs to our isDivisible() function. We can use the Integer.valueOf(str s) function to do this!
And that's all the tools we need to finish this problem! Put together, a rough solution would look like:
String[] numArray = num.split(" ");
for (int i = 0; i < numArray.length; i++) {
if (isDivisible(Integer.valueOf(numArray[i]), div1)) {
System.out.print(numArray[i] + " ");
}
}
System.out.println("): are divisible by " + div1);
UPDATE
No arrays!? Ok, in that case I think your teacher wants you to iterate through the input, checking if they are divisible, and if they are, concatenating some output strings.
So let's start by adding a couple of Strings that will later become our output to the top of our code:
class Divisible {
private String outputDiv1 = "( ";
private String outputDiv2 = "( ";
private String outputBoth = "( ";
Now, for each of these outputs we want to concatenate only the divisible numbers. We can do this without arrays by looping through the characters of our String num, and breaking apart the numbers whenever we find spaces like:
//Since we're checking for spaces, we should probably add one to the end of our string, so we can find the last number!
num += " ";
//We need to keep a record of the previous space!
int lastSpace = -1;
for (int i = 0; i < num.length(); i++) {
if (num.charAt(i) == ' ') {
//If the current character is a space, we know everything before it and the last space was a number
//Our logic will go here!
//Currently converts our string into an Integer and prints it out
int currentNumber = Integer.parseInt(num.substring(lastSpace, i));
System.out.println(currentNumber);
//Update where the last space we found was
//The '+ 1' is so we skip the spaces!
lastSpace = i + 1;
}
}
Ok, no we are iterating through our string and breaking them apart without using any arrays! All that's left to do is apply the tool we made earlier isDivisible().
Something like:
if (isDivisible(currentNum, div1)) {
outputDiv1 += currentNum;
}
Can be put into //Our logic goes here section to determine whether a number should be added to our output list or not!
Finally, we print off our finished lists:
System.out.println(outputDiv1 + " ): are divisble by " + div1);
When I enter "3" in my java code, it prints
3 will be multiplied by 3 and +1
Value is 10
Any advice as to how I should modify it, so that it calculates the sequences correctly
import javax.swing.*;
public class sequences {
/**
* #param args
*/
public static void main(String[] args) {
calculateSequences();
}//ends main
public static void calculateSequences()
{
int value;
String valueInput = JOptionPane.showInputDialog("Value");
value = Integer.parseInt(valueInput);
if(value == 1)
{
System.out.println("Value is equal to 1, closing down");
System.exit(0);
}
else if ((value%2)==0)
{
System.out.println(value + " will be divided by 2");
value = value/2;
System.out.println("Value is even " + value);
}
else
{
System.out.println(value + " will be multiplied by 3 and +1");
value = 3*value+1;
System.out.println("Value is " + value);
}
}//ends calculateSequences
}//ends class
You forgot the "go to start"
Here are the results from one test.
23 will be multiplied by 3 and + 1
Value is 70
70 will be divided by 2
Value is even 35
35 will be multiplied by 3 and + 1
Value is 106
106 will be divided by 2
Value is even 53
53 will be multiplied by 3 and + 1
Value is 160
160 will be divided by 2
Value is even 80
80 will be divided by 2
Value is even 40
40 will be divided by 2
Value is even 20
20 will be divided by 2
Value is even 10
10 will be divided by 2
Value is even 5
5 will be multiplied by 3 and + 1
Value is 16
16 will be divided by 2
Value is even 8
8 will be divided by 2
Value is even 4
4 will be divided by 2
Value is even 2
2 will be divided by 2
Value is even 1
Value is equal to 1, closing down
Here's your code with a while clause added.
import javax.swing.JOptionPane;
public class Sequences {
/**
* #param args
*/
public static void main(String[] args) {
calculateSequences();
}// ends main
public static void calculateSequences() {
int value;
String valueInput = JOptionPane.showInputDialog("Value");
value = Integer.parseInt(valueInput);
while (value > 0) {
if (value == 1) {
System.out.println("Value is equal to 1, closing down");
System.exit(0);
} else if ((value % 2) == 0) {
System.out.println(value + " will be divided by 2");
value = value / 2;
System.out.println("Value is even " + value);
} else {
System.out.println(value + " will be multiplied by 3 and + 1");
value = 3 * value + 1;
System.out.println("Value is " + value);
}
}
}// ends calculateSequences
}
You need to add iteration or recursion. Since this is Java, it would make most sense to use iteration.
This corresponds to the line "go to start ;" in the algorithm.
For this you can use a while loop, such as while(true).
public static void main(String[] args) {
process(Integer.parseInt(args[0]));
}
private static void process(int n) {
while (n != 1) {
if (n%2 == 0) {
System.out.println(n + " will be divided by 2");
n = n/2;
System.out.println("Value is even " + n);
}
else {
System.out.println(n + " will be multiplied by 3 and +1");
n = 3*n+1;
System.out.println("Value is " + n);
}
}
System.out.println("Value is equal to 1, closing down");
}
And the output:
3 will be multiplied by 3 and +1
Value is 10
10 will be divided by 2
Value is even 5
5 will be multiplied by 3 and +1
Value is 16
16 will be divided by 2
Value is even 8
8 will be divided by 2
Value is even 4
4 will be divided by 2
Value is even 2
2 will be divided by 2
Value is even 1
Value is equal to 1, closing down