I wrote these two methods to determine if a number is perfect. My prof wants me to combine them to find out if there is an odd perfect number. I know there isn't one(that is known), but I need to actually write the code to prove that.
The issue is with my main method. I tested the two test methods. I tried debugging and it gets stuck on the number 5, though I can't figure out why. Here is my code:
public class Lab6
{
public static void main (String[]args)
{
int testNum = 3;
while (testNum != sum_of_divisors(testNum) && testNum%2 != 2)
testNum++;
}
public static int sum_of_divisors(int numDiv)
{
int count = 1;
int totalDivisors = 0;
while (count < numDiv)
if (numDiv%count == 0)
{
totalDivisors = totalDivisors + count;
count++;
}
else
count++;
return totalDivisors;
}
public static boolean is_perfect(int numPerfect)
{
int count = 1;
int totalPerfect = 0;
while (totalPerfect < numPerfect)
{
totalPerfect = totalPerfect + count;
count++;
}
if (numPerfect == totalPerfect)
return true;
else
return false;
}
}
Make
testNum%2 != 2
as
testNum%2 != 0
testNum=3
while (testNum != sum_of_divisors(testNum) && testNum%2 != 2)
testNum++;
You may want to do 'testNum+=2' since you are concerned about only odd numbers and replace the testNum %2!=2 with testNum>0 or other stopping condition. Eventually your integers will overflow.
"My prof wants me to combine them to find out if there is an odd perfect number. I know there isn't one(that is known), but I need to actually write the code to prove that."
Do you mean between 3 & 2^32-1? It is not known that there are no odd perfect numbers.
Related
I am being asked to learn Java very quickly and I am struggling with not only the verbose syntax but also the expected style and approach requirements.
Given a simple FizzBuzz challenge I produced the following code:
public class FizzBuzz {
public static void main(String[] args) {
boolean hit;
for (int n = 1; n <= 30; n++) {
hit = false;
if (n % 3 == 0) {
System.out.print("Fizz");
hit = true;
}
if (n % 5 == 0) {
System.out.print("Buzz");
hit = true;
}
if (hit != true) {
System.out.print(n);
}
System.out.println();
}
}
}
Asked to refactor this code by the lead programmer and to consider possible future requirements and code managability issues I gave it some thought and produced the following refactored code:
public class FizzBuzz {
public static void main(String[] args) {
boolean hit;
for (int n = 1; n < 30; n++) {
hit = false;
hit = (n % 3 == 0) ? writeAction("Fizz") : hit;
hit = (n % 5 == 0) ? writeAction("Buzz") : hit;
if ( ! hit)
System.out.print(n);
System.out.println();
}
}
private static boolean writeAction(String actionWord){
System.out.print(actionWord);
return true;
}
}
However, the guy who set this task has moved on quite quickly and I never got any feedback on this approach. Am I going in the right direction with this or have I regressed?. To me this should scale better and would be easier to modify. I have also considered that maybe he was expecting some sort of TDD approach? I am aware that I have no tests currently.
This site isn't for reviews, but in case your question gets moved, here is some feedback (from the "clean code" perspective):
your "main" code sits in a main() method. Makes re-using it very hard.
talking about re-use - various things in there prevent re-using it
you have some duplicated code in there
you are violating the single layer of abstraction principle
How I would write something along the lines of:
public class FizzBuzz {
private final OutputStream out;
public FizzBuzz(OutputStream out) {
this.out = out;
}
public void runFizzBuzzUpTo(int n) {
for (int i = 1; i < n; i++) {
if ( writeIfTrue(n % 3 == 0, "Fizz") ) {
continue;
}
if ( writeIfTrue(n % 5 == 0, "Buzz") ) {
continue;
}
out.println(n);
}
}
private boolean writeIfTrue(boolean toCheck, String word) {
if (toCheck) {
out.println(word);
}
return toCheck;
}
public static void main(String[] args) {
new FizzBuzz(System.out).runFizzBuzzUpto(30);
}
}
Things I changed:
made the output the "core" thing of a class
provided the possibility to run for arbitrary positive numbers
Stuff still missing:
"single layere of abstraction" is still not good
instead of fixing "30" in main() - one could check for exactly one argument passed to main() - which would then be used as parameter for runFizzBuzzUpTo()
Of course, the second code is more modular and easier to modify that way. I mostly don't prefer to write the if conditions in the short way...
The method writeAction could be void because you don't have to return anything.
But you have good ideas :)
Having a String representation of a number(no decimals), what's the best way to convert it to either one of java.lang.Integer or java.lang.Long or java.math.BigInteger? The only condition is that the converted type should be of minimal datatype required to hold the number.
I've this current implementation that works fine, but I would like to know if there's a better code without exception handling.
package com.stackoverflow.programmer;
import java.math.BigInteger;
public class Test {
public static void main(String[] args) {
String number = "-12121111111111111";
Number numberObject = null;
try {
numberObject = Integer.valueOf(number);
} catch (NumberFormatException nfe) {
System.out.println("Number will not fit into Integer type. Trying Long...");
try {
numberObject = Long.valueOf(number);
} catch (NumberFormatException nfeb) {
System.out.println("Number will not fit into Long type. Trying BigInteger...");
numberObject = new BigInteger(number);
}
}
System.out.println(numberObject.getClass() + " : "
+ numberObject.toString());
}
}
From what you said, here is what I would have done:
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
public class TestSO09_39463168_StringToMinimalNumber {
public static void main(String[] args) {
List<String> strNumbers = Arrays.asList("0", //int
"123", //int
"-456", //int
"2147483700", // Long
"-2147483700", // Long
"9223372036854775900", //BigInt
"-9223372036854775900" //BigInt
);
for(String strNumber : strNumbers){
Number number = stringToMinimalNumber(strNumber);
System.out.println("The string '"+strNumber+"' is a "+number.getClass());
}
}
public static Number stringToMinimalNumber(String s){
BigInteger tempNumber = new BigInteger(s);
if(tempNumber.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0 || tempNumber.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0){
return tempNumber;
} else if(tempNumber.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0 || tempNumber.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0){
return tempNumber.longValue(); //Autobox to Long
} else {
return tempNumber.intValue(); //Autobox to Integer
}
}
}
You must use a temporary BigInteger, or else you'll end up with lazarov's solution, which is correct, but you can't really do something like that for reason mentionned in the comments.
Anyway, every BigInteger (the ones that are not returned) will be garbage collected. As for autoboxing, I don't think it's that of a bad thing. You could also make "BigInteger.valueOf(Long.MAX_VALUE))" as a constant. Maybe the compiler or the JVM will do this on its own.
I'm not really sure of how efficient it is, and using only BigInteger might be a good idea (as Spotted did), because I serioulsy doubt it would really improve the rest of your code to use the right size, and it might even be error prone if you try to use these Numbers with each other ... But again, it all depend on what you need. (and yes, using Exception as flow control is a really bad idea, but you can add a try catch on the BigInteger tempNumber = new BigInteger(s); to throw your own exception if s is not a number at all)
For recreational purpose, I have made the solution without using a BigInteger, and only with String parsing (this is still not what I recommand to do, but it was fun :)
public static final String INT_MAX_VALUE = "2147483647";
public static final String LONG_MAX_VALUE = "9223372036854775807";
public static Number stringToMinimalNumberWithoutBigInteger(String numberStr){
//Removing the minus sign to test the value
String s = (numberStr.startsWith("-") ? numberStr.substring(1,numberStr.length()) : numberStr);
if(compareStringNumber(s, LONG_MAX_VALUE) > 0){
return new BigInteger(numberStr);
} else if(compareStringNumber(s, INT_MAX_VALUE) > 0){
return new Long(numberStr);
} else {
return new Integer(numberStr);
}
}
//return postive if a > b, negative if a < b, 0 if equals;
private static int compareStringNumber(String a, String b){
if(a.length() != b.length()){
return a.length() - b.length();
}
for(int i = 0; i < a.length(); i++){
if( a.codePointAt(i) != b.codePointAt(i) ){ //Or charAt()
return a.codePointAt(i) - b.codePointAt(i);
}
}
return 0;
}
Please don't use exceptions for handling flow control, this is a serious anti-pattern (also here).
As you mentionned in the comments, the real thing you've been asked is to convert a List<String> into a List<Number>.
Also, if I understand correctly, you know that:
You should encounter only numbers without decimals
The biggest value you can encounter is possibly unbound
Based on that, the following method will do the job in a more clever way:
private static List<Number> toNumbers(List<String> strings) {
return strings.stream()
.map(BigInteger::new)
.collect(Collectors.toList());
}
Eidt: if you're not very familiar with the stream concept, here's the equivalent code without streams:
private static List<Number> toNumbers(List<String> strings) {
List<Number> numbers = new ArrayList<>();
for (String s : strings) {
numbers.add(new BigInteger(s));
}
return numbers;
}
Well if you want to do it "by hand" try something like this:
We define the max values as strings :
String intMax = "2147483647";
String longMax = "9223372036854775807";
and our number:
String ourNumber = "1234567890"
Now our logic will be simple :
We will check lenghts of strings firstly
If our numbers length < int max length : IT IS INT
If our numbers length == int max length : Check is it INT or LONG
If our numbers length > int max length :
3.1 If our numbers length < long max length : IT IS LONG
3.2 If our numbers length == long max length : Check is it LONG or BIG INTEGER
3.3 If our numbers length > long max length : IT IS BIG INTEGER
The code should look something like this (I have not tried to compile it may have syntax or other errors) :
if(ourNumber.lenght() < intMax.length ){
System.out.println("It is an Integer");
} else if(ourNumber.lenght() == intMax.length){
// it can be int if the number is between 2000000000 and 2147483647
char[] ourNumberToCharArray = ourNumber.toCharArray();
char[] intMaxToCharArray = intMax.toCharArray();
int diff = 0;
for(int i = 0; i < ourNumberToCharArray.length; i++) {
diff = Character.getNumericValue(intMaxToCharArray[i]) - Character.getNumericValue(ourNumberToCharArray[i]);
if(diff > 0) {
System.out.println("It is a Long");
break;
} else if(diff < 0) {
System.out.println("It is an Integer");
break;
}
}
if(diff == 0){
System.out.println("It is an Integer");
}
} else {
if(ourNumber.lenght() < longMax.length()) {
System.out.println("It is a Long");
} else if(ourNumber.lenght() == longMax.length()){
char[] ourNumberToCharArray = ourNumber.toCharArray();
char[] longMaxToCharArray = longMax.toCharArray();
int diff = 0;
for(int i = 0; i < ourNumberToCharArray.length; i++) {
diff = Character.getNumericValue(longMaxToCharArray[i]) - Character.getNumericValue(ourNumberToCharArray[i]);
if(diff > 0) {
System.out.println("It is a BigInteger");
break;
} else if(diff < 0) {
System.out.println("It is a Long");
break;
}
}
if(diff == 0){
System.out.println("It is a Long");
}
} else {
System.out.println("It is a BigInteger");
}
}
Then logic that checks if the numbers match or not is the same in both cases you can but it in a function for example.
I am aware there are multiple threads like my assignment below, but I just can't figure it out. I can't exactly figure out the mistake. Help would be appreciated.
I am trying to do this program:
Everything works fine unless I input the same chains or similar (for example ACTG and ACTG or ACTG and ACTGCCCC), when it tells me
string index out of range
This is that part of my code:
int tries=0;
int pos=-1;
int k;
for (int i=0; i<longDNA.length(); i++) {
tries=0;
k=i;
for (int j=0; j<shortDNA.length(); j++) {
char s=shortDNA.charAt(j);
char l=longDNA.charAt(k);
if (canConnect(s,l)) {
tries+=1;
k+=1;
}
}
if (tries==shortDNA.length()-1) {
pos=i-1;
break;
}
}
Let's call the two DNA strings longer and shorter. In order for shorter to attach somewhere on longer, a sequence of bases complementary to shorter must be found somewhere in longer, e.g. if there is ACGT in shorter, then you need to find TGCA somewhere in longer.
So, if you take shorter and flip all of its bases to their complements:
char[] cs = shorter.toCharArray();
for (int i = 0; i < cs.length; ++i) {
// getComplement changes A->T, C->G, G->C, T->A,
// and throws an exception in all other cases
cs[i] = getComplement(cs[i]);
}
String shorterComplement = new String(cs);
For the examples given in your question, the complement of TTGCC is AACGG, and the complement of TGC is ACG.
Then all you have to do is to find shorterComplement within longer. You can do this trivially using indexOf:
return longer.indexOf(shorterComplement);
Of course, if the point of the exercise is to learn how to do string matching, you can look at well-known algorithms for doing the equivalent of indexOf. For instance, Wikipedia has a category for String matching algorithms.
I tried to replicate your full code as fast as I could, I'm not sure if I fixed the problem but you don't get any errors.
Please try it and see if it works.
I hope you get this in time and good luck!
import java.util.Arrays;
public class DNA {
public static void main(String[] args) {
System.out.println(findFirstMatchingPosition("ACTG", "ACTG"));
}
public static int findFirstMatchingPosition(String shortDNA, String longDNA) {
int positionInLong = 0;
int positionInShort;
while (positionInLong < longDNA.length()) {
positionInShort = 0;
while(positionInShort < shortDNA.length()) {
String s = shortDNA.substring(positionInShort, positionInShort + 1);
if(positionInShort + positionInLong + 1 > longDNA.length()) {
break;
}
String l = longDNA.substring(positionInShort + positionInLong, positionInShort + positionInLong + 1);
if(canConnect(s, l)) {
positionInShort++;
if(positionInShort == shortDNA.length()) {
return positionInLong;
}
} else {
break;
}
}
positionInLong++;
if(positionInLong == longDNA.length()) {
return -1;
}
}
return -1;
}
private static String[] connections = {
"AT",
"TA",
"GC",
"CG"
};
private static boolean canConnect(String s, String l) {
if(Arrays.asList(connections).contains((s+l).toUpperCase())) {
return true;
} else {
return false;
}
}
}
I finally changed something with the k as Faraz had mentioned above to make sure the charAt does not get used when k overrides the length of the string and the program worked marvelously!
The code was changed to the following:
int tries=0;
int pos=-1;
int k;
for (int i=0; i<longDNA.length(); i++) {
tries=0;
k=i;
for (int j=0; j<shortDNA.length(); j++) {
if (k<longDNA.length()) {
char s=shortDNA.charAt(j);
char l=longDNA.charAt(k);
if ((s=='A' && l=='T') || (s=='T' && l=='A') || (s=='G' && l=='C') || (s=='C' && l=='G')) {
tries+=1;
k+=1;
}
}
}
if (tries==shortDNA.length()) {
pos=i;
break;
}
}
I am not sure how aesthetically pleasing or correct this excerpt is but - it completely solved my problem, and just 2 minutes before the deadline! :)
A huge thanks to all of you for spending some time to help me!!
import java.util.*;
class A{
static int count=0;
static String s;
public static void main(String z[]){
int n;
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
System.out.println(noOfBouncy(n));
}
public static int noOfBouncy(int k){
int limit=(int)Math.pow(10,k);
s=new String("1");
int num=Integer.parseInt(s);
while(num<limit){
if(isIncreasing(s) || isDecreasing(s) ){
}
else{
count++;
}
num++;
s=new String(Integer.toString(Integer.parseInt(s)+1));
}
count=limit-count;
return count;
}
}
public static boolean isIncreasing(String s){
int len=s.length();
for(int i=0;i<len-1;i++){
if(s.charAt(i)>s.charAt(i+1)){
return false;
}
}
return true;
}
public static boolean isDecreasing(String s){
int len=s.length();
for(int i=0;i<len-1;i++){
if(s.charAt(i)<s.charAt(i+1)){
return false;
}
}
return true;
}
I have given the definitions to the two functions used isIncreasing() & isDecresing()
The program runs well for the value of n<7 but does not respond for values above it, Why ?
I accept the programming style is very immature,please ignore.
I've tried to execute it with n=7 and it finishes in 810ms, returning 30817.
However, I recommend to you to optimize the performance of your program by saving unnecessary object instantiation: It will be better if you maintain the counter in num, and convert it to string just once, at the beginning of the loop:
int num=1;
while (num < limit)
{
s=Integer.toString(num);
if (isIncreasing(s) || isDecreasing(s))
{
}
else
{
count++;
}
num++;
}
Like this it takes just 450ms to finish.
The program was not actually stuck but it is taking way too much time to complete its execution when value of 'n' is larger.
So now the question is, I need to optimize the code to take minimum time #Little have an optimization bit that's not enough.
Any hint would be appreciable.
To increase the performance you should avoid the conversation to String and do the check with numbers.
As it doesn't matter for the result if you start the comparison from left to right or from right to left one computational solution could be.
as pseudo code
1) compare the value of the right most digit with the digit on it's left
2) is it lower --> we found a decreasing pair
3) else check if it is bigger --> we found an increasing pair
4) else --> not a bouncy pair
5) if we found already one decreasing and one increasing pair it's bouncy number
6) divide the number by ten if it's bigger then ten repeat with step 1)
The method to check if it's a bouncy number could look like this
static boolean isBouncyNumber(int number) {
boolean increasingNumber = false;
boolean decreasingNumber = false;
int previousUnitPosition = number % 10;
int remainder = number / 10;
while (remainder > 0) {
// step 1
int currentUnitPosition = remainder % 10;
if (currentUnitPosition > previousUnitPosition) {
// step 2
decreasingNumber = true;
} else if (currentUnitPosition < previousUnitPosition) {
// step 3
increasingNumber = true;
}
// step 5
if (decreasingNumber && increasingNumber) {
return true;
}
// step 6
previousUnitPosition = currentUnitPosition;
remainder = remainder / 10;
}
return decreasingNumber && increasingNumber;
}
I'm pretty new to java, but I'm trying to make a simulation of the finger game, 'Sticks', using my limited knowledge. This may not be the neatest, but if you're going to make a suggestion on me to do something, link a page explaining what that thing is, and I'll read it.
Ok, so the issue comes up basically when I call a method to decide who's turn it is and trying to return the value for the "count" up to 5, but it's not returning to main()
public static int TurnCalcBB(int PLH, int PRH, int BRH, int BLH, int Death)
{
//Attacking with bot Right hand
Random botAtk = new Random();
if(botAtk.nextInt(2) == 1 && PRH <= 5)
{
PRH = BRH + PRH;
JOptionPane.showMessageDialog(null,"Your right hand is now at " + PRH);
return PRH;
} else if(botAtk.nextInt(2) == 0 && PLH <= 5){
PLH = BRH + PLH;
JOptionPane.showMessageDialog(null, "Your left hand is now at " + PLH);
return PLH;
}
return Death;
}
Death is there because I was getting an error telling me that I always need to return SOMETHING so I'm returning a static value.
Basically, the problem is getting PLH (player left hand) or PRH (player right hand) to return to main. If I'm not wrong, they should return as their initial variable name (PL, and PR) with the returned value correct? If not, what can I do to fix this?
The code is a lot larger than this, and this issue is happening throughout the whole program, so I'm showing just 1 method and assuming they're all the same issue; the methods are almost all the same.
Also, while I'm typing a question already, is nextInt() the best way to do a random number generator? When I had it as nextInt(1) it was exclusively attacking the left hand, and when I switched it to nextInt(2) now it's attacking both, but occasionally the code... "crashes" (what I mean by crashes is that it generates a number outside of what the If statements are looking for). I obviously need to to generate either a 1 or a 2 (or 0 and 1 if 0 counts).
You can change your code to
public static Integer TurnCalcBB(int PLH, int PRH, int BRH, int BLH, int Death)
{
//Attacking with bot Right hand
Random botAtk = new Random();
if(botAtk.nextInt(2) == 1 && PRH <= 5)
{
PRH = BRH + PRH;
JOptionPane.showMessageDialog(null,"Your right hand is now at " + PRH);
return PRH;
} else if(botAtk.nextInt(2) == 0 && PLH <= 5){
PLH = BRH + PLH;
JOptionPane.showMessageDialog(null, "Your left hand is now at " + PLH);
return PLH;
}
return null;
}
NOTE: make sure you first check for null values where you call this function.
You are generating random number twice, this is why you can observe "strange" behvior.
Random botAtk = new Random();
if(botAtk.nextInt(2) == 1 && PRH <= 5) {
...
}
else if(botAtk.nextInt(2) == 0 && PLH <= 5) {
...
}
Try generating random only once:
Random botAtk = new Random();
boolean right = botAtk.nextInt(2) == 1; // flip coin only once
if(right && PRH <= 5) {
...
}
else if(!right && PLH <= 5) {
...
}
I know the answer will not get accepted, because there is an accepted one, but nevertheless:
I suspect that you have a wrong understanding of method parameter passing in Java.
What I read from your question and comments is that you expect this to work:
public static int psInt = 0;
static void main() {
int someNumber = 1;
int someOtherNumber = 5;
method1( someNumber, someOtherNumber );
// You expect "someNumber" to be 6 right now.
// But in fact, the value will be unchanged.
// What WILL work: psInt is 0 now
method3(); // this method will modify the static class var
// psInt is 5 now.
}
static void method1( int numParam, int someothervalue ){
numParam = numParam + someothervalue;
}
static void method2( int someNumber, int someothervalue ){
someNumber = someNumber + someothervalue; // <- same name won't work either!
}
public static void method3(){
psInt = 5;
}
But in Java method arguments are passed by value. That is: a copy!
So no matter how you name the variables and arguments, you will never have an "out" argument here.
What you can do:
In a static method, you can use and modify static class variables.
In a non-static method, you can use and modify non-static and static class variables.
You can pass a State-Object, of which you can modify field values.
You can return a value.
... there are more possibilites. These just to start with.
In your case, 4. does not make so much sense, because you wouldn't know if it is the new right or left hand value.