Happy numbers checker not working correctly - java

int Cnt(){
return Count (10);
}
int Count (int init){
int u = init % 10;
int t = (init % 100) - u;
int u2 = u * u;
int t2 = t * t;
int m = u2 + t2;
if(m <= 1)
System.out.println("Happy!");
else {
return Count (m);
}
This code should (in theory) check if number is Happy, and if it's not sets initial value to be same as the result and whole process repeats.
Infinite loop should occur if number is not happy.
However none of this happens, does anyone know how to make this work?

According to the Wiki article that you linked, you have to repeat the process of summing the digits of the digits in each number. For the example of 7:
7^2 = 49
49 = 4^2 + 9^2 = 16 + 81 = 97
97 = 9^2 + 7^2 = 81 + 49 = 130
130 = 1^2 + 3^2 = 10
10 = 1^2 = 1
I see a few problems with your code. First, you haven't divided your tens digit by 10, which means for the number 52, you will get u = 2, and t = 50, rather than 5. This part, I'm sure you can easily fix.
Second, it looks like you will never reach a conclusion if your number is unhappy. For example with the number 4, you will reach 16, 37, 72, 53, 34, 25, 29, 85, 89, 145, 42, 20, 4. But your program, since you have no way of checking that you've entered a loop, will run until you run out of memory.

Try using the approach as outlined in the article you referenced:
private static boolean isHappy(int number)
{
List<Integer> set = new ArrayList<Integer>();
while (number > 1 && !set.contains(number))
{
set.add(number);
number = sumSquaresOfDigits(number);
}
return number == 1;
}
private static int sumSquaresOfDigits(int number)
{
String numberString = Integer.toString(number);
int result = 0;
for (char character : numberString.toCharArray())
{
int digit = Character.digit(character, 10);
result += digit * digit;
}
return result;
}
This can be done more efficiently by computing the squares of all 10 digits (0-9) and storing the results in an integer array.

Since this is homework I am not putting in the answer... but here is the clue..
You are not handling 3 digit numbers well.
t=init%100-u computes to 10%100-0 = 10
and once m=u2+t2 i.e. m=0+100 reaches to 100 and your program doesn't handle 3 digit numbers. Hope this helps.
add following...
int h = init/100;
int h2 = h * h;
int m = u2+t2+h2;
and it should keep you going... :)

import java.io.*;
class happy_no
{
void happy(double n)
{
int c=0;
double s=0;
double d,p,i,_sa;
for(i=1;i<=n;i++)
{
while(n!=0)
{
d=n%10;
p=d*d;
s=s+p;
n=n/10;
}
if(s==1)
{
System.out.println("HAPPY NO.");
break;
}
else
{
n=s;
}
}
}
public static void main()throws IOException
{
InputStreamReader read=new InputStreamReader(System.in);
BufferedReader in=new BufferedReader(read);
double a;
System.out.println("ENTER A NO.");
a=Double.parseDouble(in.readLine());
happy_no obj=new happy_no();
obj.happy(a);
}

Related

How to reverse the order of an int without turning it into a string

I have been tasked with the assignment of creating a method that will take the 3 digit int input by the user and output its reverse (123 - 321). I am not allowed to convert the int to a string or I will lose points, I also am not allowed to print anywhere other than main.
public class Lab01
{
public int sumTheDigits(int num)
{
int sum = 0;
while(num > 0)
{
sum = sum + num % 10;
num = num/10;
}
return sum;
}
public int reverseTheOrder(int reverse)
{
return reverse;
}
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
Lab01 lab = new Lab01();
System.out.println("Enter a three digit number: ");
int theNum = input.nextInt();
int theSum = lab.sumTheDigits(theNum);
int theReverse = lab.reverseTheOrder(theSum);
System.out.println("The sum of the digits of " + theNum + " is " + theSum);
}
You need to use the following.
% the remainder operator
/ the division operator
* multiplication.
+ addition
Say you have a number 987
n = 987
r = n % 10 = 7 remainder when dividing by 10
n = n/10 = 98 integer division
Now repeat with n until n = 0, keeping track of r.
Once you understand this you can experiment (perhaps on paper first) to see how
to put them back in reverse order (using the last two operators). But remember that numbers ending in 0 like 980 will become 89 since leading 0's are dropped.
You can use below method to calculate reverse of a number.
public int reverseTheOrder(int reverse){
int result = 0;
while(reverse != 0){
int rem = reverse%10;
result = (result *10) + rem;
reverse /= 10;
}
return result;
}

Java Display 10 multiples of a number and sum them

On this program, it asks you a number, then displays 10 multiples of that number and then sums them but it has to be like this:
Number = 6;
06, 12, 18, 24, 30, 36, 42, 48, 54, 60
60, 54, 48, 42, 36, 30, 24, 18, 12, 06
Sum = 324
The part of displaying the numbers is no problem, the problem is when i have to sum them. I tried to use lists to save the numbers of each row and then use the first row/list and sum it but i can't get it to work.
ArrayList<Integer> i1 = new ArrayList();
ArrayList<Integer> i2 = new ArrayList();
System.out.println("Introduce un nĂºmero:\n"); // Asks you a number
int n1=scan.nextInt();
int add_i = 0;
int rest_i = n1 * 11;
i1.add(add_i);
i2.add(rest_i);
while (add_i <= n1 * 9) // while add_i is less or equal to n1 * 9
{
add_i += n1; // suma n1 a i
System.out.print(i1 + " "); // Prints the result
}
System.out.println(" ");
while (rest_i >= 10) // while rest_i is greater or equal than 10
{
rest_i -= n1; // Resta n1 a i
System.out.print(i2 + " "); // Prints result
}
Also in my program the mults do not show up.
Not sure what logic you are trying to undertake, but it seems a lot more difficult than
Scanner scan = new Scanner(System.in);
System.out.println("Enter number : ");
int input = scan.nextInt ();
int sum = 0;
for (int loop = 1; loop <= 10; loop++) {
int out = loop * input;
sum += out;
System.out.println(out);
}
// and down
for (int loop = 10; loop >= 1; loop--) {
int out = loop * input;
System.out.println(out);
}
System.out.println("sum is "+ sum);
try this:
int sum = IntStream.iterate(startNumber, n -> n+startNumber)
.limit(10)
.peek(System.out::println)
.sum();
Disclaimer because of downvotes. This is an alternate solution. You can look at it when you understand loops well enough I guess.

Random - nextInt(int y) isn't able to give me 18 even integers in a row when 'int y' % 2 == 0 && 'int y' != a power of 2

sorry for that title but I wanted to pack as much information about my problem in as little space as possible without being too confusing.
So, I have a loop which runs n times and each time it uses a = r.nextInt(int y); to generate an int and if all n integers generated are even numbers, then the program "returns true".
The weird thing is: if I chose n to be 18 or higher while y is and even number which is not a power of 2, then the programm will not "termintate successfully".
I love to help you help me, and can take a heavy dose of criticism.
(I know I'm asking about the Random/nextInt(int) topic but I will also take tips for better coding)
EDIT: I looked into the Documentation for Java8 befor I posted here and for powers of two the method uses a different way of producing the random number.
What I don't understand is why is 18 the breakpoint for consecutive even numbers and why does it work with odd numbers for nextInt(int)?
So the following code will work with howManyInts = 16 or 17 but not 18 (or higher) when nextIntValue is an even number which is not a power of two (6,10,12...)
It works with howManyInts = 25 and nextIntValue = 8 in less than 20 seconds
import java.util.*;
class test{
public static void main(String[] args) {
boolean win = false;
int areEven = 0;
long loopCounter = 0; // The loopCounter is used to control the maximum number of loops should be run incase the loop is endless
int howManyInts = 18;
int nextIntValue = 6; // nextIntValue = 6 or 10 won't work while all powers of 2 work fine
// also, I don't want an odd value as that would change to odds towards odd values...
while(win == false){
loopCounter += 1;
areEven = 0;
Random r = new Random();
int[] num = new int[howManyInts];
for(int a = 0; a < num.length; a++){
num[a] = r.nextInt(nextIntValue);
if(num[a] % 2 == 0){
areEven += 1;
}
}
if(areEven == num.length || loopCounter >= 10000000){
win = true;
System.out.println("It took " + loopCounter + " loops to get " + num.length + " random values which are all even.");
}
}
}
}
If you use SecureRandom instead of Random, your program will finish fairly quickly.
Another way would be to use nextDouble instead
num[a] = (int) (r.nextDouble() * nextIntValue);
The problem with Random.nextInt(int n) is I believe hidden within its implementation and you can read about it in its javadoc.
The algorithm is slightly tricky. It rejects values that would result
in an uneven distribution (due to the fact that 2^31 is not divisible
by n). The probability of a value being rejected depends on n. The
worst case is n=2^30+1, for which the probability of a reject is 1/2,
and the expected number of iterations before the loop terminates is 2.
The algorithm treats the case where n is a power of two specially: it
returns the correct number of high-order bits from the underlying
pseudo-random number generator. In the absence of special treatment,
the correct number of low-order bits would be returned. Linear
congruential pseudo-random number generators such as the one
implemented by this class are known to have short periods in the
sequence of values of their low-order bits. Thus, this special case
greatly increases the length of the sequence of values returned by
successive calls to this method if n is a small power of two.
The implementation looks like this:
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
}
While the next method looks like this (I've replaced the constants with literals)
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
(I suppose that 48-31 == 17 is purely coincidental)
Interesting question!
I have added some statistic-gathering to the code:
import java.util.*;
public class J {
static Random r = new Random();
private static class Stats {
long s[];
public Stats(int n) { this.s = new long[n]; }
public String toString() {
return Arrays.toString(s);
}
}
public static void test(int target, int options) {
boolean win = false;
Stats s = new Stats(target);
for (long iterations = 0; !win; iterations ++) {
int even = 0;
for (int i = 0; i < target; i++) {
if ((r.nextInt(options) % 2) != 0) {
s.s[i] ++;
break;
} else {
even ++;
}
}
if (even == target) {
win = true;
System.out.println(
"It took " + iterations + " loops to get " + target
+ " random values which are all even. Stats: " + s);
} else if (iterations >= 1E8) {
win = true;
System.out.println(iterations + ": " + s);
}
}
}
public static void main(String args[]) {
test(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
}
}
The code now ends if no sequence is found after 100M tries; and always stores how far it managed to get before failing (= drawing an odd number).
These are some runs:
18 9: It took 57235 loops to get 18 random values which are all even. Stats: [25401, 14081, 7864, 4328, 2508, 1366, 747, 390, 263, 126, 76, 38, 28, 4, 8, 4, 2, 1]
18 8: It took 48612 loops to get 18 random values which are all even. Stats: [24285, 12336, 6066, 2981, 1436, 738, 385, 197, 95, 43, 23, 10, 8, 7, 1, 0, 0, 1]
18 7: It took 23302 loops to get 18 random values which are all even. Stats: [10062, 5712, 3174, 1877, 1101, 590, 331, 190, 98, 59, 44, 31, 18, 8, 5, 2, 0, 0]
18 6: Aborted after 100000000 tries: [49997688, 24993911, 12503043, 6272129, 3113557, 1544194, 788879, 393680, 205236, 89264, 45016, 35858, 5340, 9155, 763, 1525, 0, 763]
So, for those particular values (100M attempts at runs of 18 even numbers, throwing 6-sided dice), there were 0 cases where the run bailed out because of the 17th number, but 763(!) where it bailed out because of the last number!
It definitely looks like a higher-quality PRNG is needed, such as the one mentioned by #radoh.
Probabilistically speaking, you would expect to find runs of N even throws of a fair coin with probability 1/(2^N); and you would expect to collect stats where each entry would be 1/2 the previous one. Encountering 0, 763 indicates a strong bias.
The issue is almost certainly with r.nextInt(nextIntValue);. Here you are requesting a random integer between 0 and 5. I cannot understand specifically why 18 is the break point but the chances a sequence of random positive integers less than a small number to be all even must reduce as the limit reduces.
I note that increasing that value from 6 to 100 still does not find length-18 even sequences. Perhaps the algorithm behind the scenes somehow influences the statistics.
Seems like the random generator doesn't allow 18 consecutive even numbers, when your maxRandom is even, starting at 6.
I changed the code a bit to demonstrate how the 18th random is always odd:
class NextIntWeirdness {
public static void main(String[] args) {
int maxRandom = 6;
Random r = new Random();
for (int i = 0; i < 100; i++) {
int evenNumbers = 17;
int evenResults;
do {
evenResults = 0;
for (int j = 0; j < evenNumbers; j++) {
int num = r.nextInt(maxRandom);
if (num % 2 != 0) {
break;
} else {
evenResults++;
}
}
} while (evenResults < evenNumbers);
System.out.println(r.nextInt(maxRandom));
}
}
}

Binary Calculator Assignment

For this lab, you will enter two numbers in base ten and translate
them to binary. You will then add the numbers in binary and print out
the result. All numbers entered will be between 0 and 255, inclusive,
and binary output is limited to 8 bits. This means that the sum of the
two added numbers will also be limited to 8 bits. If the sum of the
two numbers is more than 8 bits, please print the first 8 digits of
the sum and the message "Error: overflow". Your program should
represent binary numbers using integer arrays, with the ones digit
(2^0) stored at index 0, the twos digit (2^1) stored at index 1, all
the way up to the 2^7 digit stored at index 7. Your program should
include the following methods:
int[] convertToBinary(int b) Translates the parameter to a binary value and returns it stored as an array of ints.
void printBin(int b[]) Outputs the binary number stored in the array on one line. Please note, there should be exactly one space
between each output 0 or 1.
int[] addBin(int a[], int b[]) Adds the two binary numbers stored in the arrays, and returns the sum in a new array of ints.
When entering my code into CodeRunner (which tests the code and returns a grade back depending on the results of each test) I cannot seem to pass one of the tests. This is the message that I am getting:
*You had 43 out of 44 tests pass correctly. Your score is 97%.
The tests that failed were: Test: addBin() method Incorrect: Incorrect number returned*
Heres my code:
import java.util.Scanner;
class Main {
public static int[] convertToBinary(int a) {
int[] bin = {0, 0, 0, 0, 0, 0, 0, 0};
for (int i = bin.length - 1; i >= 0; i--) {
bin[i] = a % 2;
a = a / 2;
}
return bin;
}
public static void printBin(int[] b) {
int z;
for (z = 0; z < b.length; z++) {
System.out.print(b[z] + " ");
}
System.out.println();
}
public static int[] addBin(int[] c, int[] d) {
int[] added = new int[8];
int remain = 0;
for (int x = added.length - 1; x >= 0; x--) {
added[x] = (c[x] + d[x] + remain) % 2;
remain = (c[x] + d[x] + remain) / 2;
}
if (added[0] + c[0] + d[0] == 1) {
added[0] = 1;
} else if ((added[0] + c[0] + d[0] == 2) || (added[0] + c[0] + d[0] == 3)) {
System.out.println("Error: overflow");
}
return added;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a base ten number between 0 and 255, inclusive.");
int num1 = scan.nextInt();
System.out.println("Enter a base ten number between 0 and 255, inclusive.");
int num2 = scan.nextInt();
int[] bin;
bin = convertToBinary(num1);
System.out.println("First binary number:");
printBin(bin);
int[] bin1 = bin;
bin = convertToBinary(num2);
System.out.println("Second binary number:");
printBin(bin);
int[] bin2 = bin;
System.out.println("Added:");
{
printBin(addBin(bin1, bin2));
}
}
}
If anyone could take a look at my code above and see if they could tell me what needs to be changed to fix the addbin() method so that it passes all of the tests, that'd be great! Any help is greatly appreciated even if you are not sure it would work! Thanks!
Hi first of all pardon my English but i guess your assignment accepts 1 and 255 too. So i added two of them and get 1 0 0 0 0 0 0 0 in your code. But i think it need to be 0 0 0 0 0 0 0 0 with an overflow error. So i changed your code a little bit.
public static int[] addBin(int[] c, int[] d) {
int[] added = new int[8];
int remain = 0;
for (int x = added.length - 1; x >= 0; x--) {
added[x] = (c[x] + d[x] + remain) % 2;
remain = (c[x] + d[x] + remain) / 2;
}
if (remain!=0) {
System.out.println("Error: overflow");
}
return added;
}
It's my first answer on the site so i hope it works for your test

The Collatz Sequence problem

I'm trying to solve this problem, its not a homework question, its just code I'm submitting to uva.onlinejudge.org so I can learn better java trough examples. Here is the problem sample input :
3 100
34 100
75 250
27 2147483647
101 304
101 303
-1 -1
Here is simple output :
Case 1: A = 3, limit = 100, number of terms = 8
Case 2: A = 34, limit = 100, number of terms = 14
Case 3: A = 75, limit = 250, number of terms = 3
Case 4: A = 27, limit = 2147483647, number of terms = 112
Case 5: A = 101, limit = 304, number of terms = 26
Case 6: A = 101, limit = 303, number of terms = 1
The thing is this has to execute within 3sec time interval otherwise your question won't be accepted as solution, here is with what I've come up so far, its working as it should just the execution time is not within 3 seconds, here is code :
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
int start;
int limit;
int terms;
int a = 0;
while (stdin.hasNext()) {
start = stdin.nextInt();
limit = stdin.nextInt();
if (start > 0) {
terms = getLength(start, limit);
a++;
} else {
break;
}
System.out.println("Case "+a+": A = "+start+", limit = "+limit+", number of terms = "+terms);
}
}
public static int getLength(int x, int y) {
int length = 1;
while (x != 1) {
if (x <= y) {
if ( x % 2 == 0) {
x = x / 2;
length++;
}else{
x = x * 3 + 1;
length++;
}
} else {
length--;
break;
}
}
return length;
}
}
And yes here is how its meant to be solved :
An algorithm given by Lothar Collatz produces sequences of integers, and is described as follows:
Step 1:
Choose an arbitrary positive integer A as the first item in the sequence.
Step 2:
If A = 1 then stop.
Step 3:
If A is even, then replace A by A / 2 and go to step 2.
Step 4:
If A is odd, then replace A by 3 * A + 1 and go to step 2.
And yes my question is how can I make it work inside 3 seconds time interval?
From Googling I found this thread where a couple of other people have had the same problem and the solution is to use 64-bit arithmetic instead of 32-bit arithmetic.
Try changing int to long and see if that helps.

Categories

Resources