I know my code can be simpler and more efficient... My code is supposed to grab the biggest set of 5 digits. It works, except it only is grabbing 3 digits, what would i need to modify to change that?
public class thousandDigits {
public static void main(String[] args) {
int greatest = 0;
String num = ("73167176531330624919225119674426574742355349194934"
+ "96983520312774506326239578318016984801869478851843"
+ "85861560789112949495459501737958331952853208805511"
+ "12540698747158523863050715693290963295227443043557"
+ "66896648950445244523161731856403098711121722383113"
+ "62229893423380308135336276614282806444486645238749"
+ "30358907296290491560440772390713810515859307960866"
+ "70172427121883998797908792274921901699720888093776"
+ "65727333001053367881220235421809751254540594752243"
+ "52584907711670556013604839586446706324415722155397"
+ "53697817977846174064955149290862569321978468622482"
+ "83972241375657056057490261407972968652414535100474"
+ "82166370484403199890008895243450658541227588666881"
+ "16427171479924442928230863465674813919123162824586"
+ "17866458359124566529476545682848912883142607690042"
+ "24219022671055626321111109370544217506941658960408"
+ "07198403850962455444362981230987879927244284909188"
+ "84580156166097919133875499200524063689912560717606"
+ "05886116467109405077541002256983155200055935729725"
+ "71636269561882670428252483600823257530420752963450");
for (int n = 0; n < num.length() - 5; n++) {
greatest = ((num.charAt(n)) + (num.charAt(n+1)) + (num.charAt(n+2)) + (num.charAt(n+3))
+ (num.charAt(n+4)));
if (greatest > n) {
n = greatest;
}
}
System.out.print(greatest);
}
}
OUTPUT:
357
I think you want to use String.substring(int, int) to iterate all possible 5 character substrings, and then you might use Math.max(int, int) to update greatest. Something like
int greatest = Integer.MIN_VALUE;
for (int i = 0; i < num.length() - 4; i++) {
// int value = Integer.parseInt(num.substring(i, i + 5));
int value = Integer.parseInt(String.valueOf(num.charAt(i))
+ num.charAt(1 + i) + num.charAt(2 + i) + num.charAt(3 + i)
+ num.charAt(4 + i));
greatest = Math.max(greatest, value);
}
System.out.println(greatest);
I get 99890.
I think you are trying to add 5 consecutive characters to get sum, and store starting index of highest sum.
But you should be using Character.getNumricValue(char) to convert (num.charAt(n)) to numeric value and then add.
greatest = Character.getNumericValue((num.charAt(n)) + Character.getNumericValue((num.charAt(n+1)) + Character.getNumericValue((num.charAt(n+2)) +
Character.getNumericValue((num.charAt(n+3)) +
Character.getNumericValue((num.charAt(n+4));
You need a valirable to store old value to compare and index
if(greatest > oldGreatest) {
index = n;
}
Then finally print using index out side loop:
System.out.print((num.charAt(index)) + (num.charAt(index+1) + (num.charAt(index +2)) + (num.charAt(index +3)) + (num.charAt(index +)));
Although #ElliottFrisch and #dave provides more elegant answer, I tried to modify from your original version and here is my code (I have tested it):
public class ThousandDigits {
public static void main(String[] args) {
int greatest = 0;
String num = ("73167176531330624919225119674426574742355349194934"
+ "96983520312774506326239578318016984801869478851843"
+ "85861560789112949495459501737958331952853208805511"
+ "12540698747158523863050715693290963295227443043557"
+ "66896648950445244523161731856403098711121722383113"
+ "62229893423380308135336276614282806444486645238749"
+ "30358907296290491560440772390713810515859307960866"
+ "70172427121883998797908792274921901699720888093776"
+ "65727333001053367881220235421809751254540594752243"
+ "52584907711670556013604839586446706324415722155397"
+ "53697817977846174064955149290862569321978468622482"
+ "83972241375657056057490261407972968652414535100474"
+ "82166370484403199890008895243450658541227588666881"
+ "16427171479924442928230863465674813919123162824586"
+ "17866458359124566529476545682848912883142607690042"
+ "24219022671055626321111109370544217506941658960408"
+ "07198403850962455444362981230987879927244284909188"
+ "84580156166097919133875499200524063689912560717606"
+ "05886116467109405077541002256983155200055935729725"
+ "71636269561882670428252483600823257530420752963450");
int max = -1;
for (int n = 0; n < num.length() - 4; n++) {
greatest = ((num.charAt(n) - '0') * 10000 + (num.charAt(n + 1) - '0') * 1000
+ (num.charAt(n + 2) - '0') * 100 + (num.charAt(n + 3) - '0') * 10 + (num.charAt(n + 4) - '0'));
if (max < greatest) {
max = greatest;
}
}
System.out.print(max);
}
}
I think you'll find it's not grabbing three digits, but rather the sum of the six characters you are pulling out is a 3-digit number.
If you're after the largest five digit number, you need to extract five digits (not six) as you do and assign them a weight. So the first digit must be multiplied by 10,000, the second by 1,000 and so on.
But there's more: you're are getting the character at an index within your string. This is not what you want as it is not the same as the numeric value of that character. For that you need:
num.charAt(n) - '0'
These changes should allow you to correct your algorithm as it stands.
A more efficient approach would be to extract 5-digit sub-strings and convert them to integers. The first one would be:
Integer.parseInt(num.subString(0, 5));
You can iterate to get each one to find the greatest.
Related
Im trying to solve EulerProblem8 https://projecteuler.net/problem=8 and i just don't get it , what am i doing wrong ? I tried before with a file and ArrayList but couldn't pull it off ... Whats wrong , the subtsrings , the loops , the *= ... i dont know what to do anymore?
package largestproductinaseries_ep8;
//The four adjacent digits in the 1000-digit number
//that have the greatest product are 9 × 9 × 8 × 9 = 5832.
//Find the thirteen adjacent digits in the 1000-digit number
//that have the greatest product. What is the value of this product?
public class LargestProductInASeries_EP8 {
public static void main(String[] args){
String bigNum = "73167176531330624919225119674426574742355349194934" +
"96983520312774506326239578318016984801869478851843" +
"85861560789112949495459501737958331952853208805511" +
"12540698747158523863050715693290963295227443043557" +
"66896648950445244523161731856403098711121722383113" +
"62229893423380308135336276614282806444486645238749" +
"30358907296290491560440772390713810515859307960866" +
"70172427121883998797908792274921901699720888093776" +
"65727333001053367881220235421809751254540594752243" +
"52584907711670556013604839586446706324415722155397" +
"53697817977846174064955149290862569321978468622482" +
"83972241375657056057490261407972968652414535100474" +
"82166370484403199890008895243450658541227588666881" +
"16427171479924442928230863465674813919123162824586" +
"17866458359124566529476545682848912883142607690042" +
"24219022671055626321111109370544217506941658960408" +
"07198403850962455444362981230987879927244284909188" +
"84580156166097919133875499200524063689912560717606" +
"05886116467109405077541002256983155200055935729725" +
"71636269561882670428252483600823257530420752963450";
int a = 0;
String peace = "";
String onePeace = "";
int onePeaceNum = 0;
int multi = 1;
int maxMulti = 0;
while(a<bigNum.length()-12){
peace = bigNum.substring(a, a+13);
if(!peace.contains("0")){
for(int i = 12; i>=0; i--){
onePeace = peace.substring(i, i+1);
onePeaceNum = Integer.parseInt(onePeace);
multi *= onePeaceNum;
if(multi>maxMulti){
maxMulti = multi;
}
}
multi = 1;
}
a++;
}
System.out.println(maxMulti);
}
}
//23514624000 this is Euler answer
// 2091059712 this is my output
You have a problem in your implementation, you never reset the mult value so you keep multiplying and you don't stop after 13 numbers.
Your code should be:
if (mult > maxMult) {
maxMult = mult;
mult = 1;
} else {
mult = 1;
}
I need to print the factors of a perfect number. Here's the gist of my main class:
ArrayList<Integer> perfNums = new ArrayList<>();
Scanner in = new Scanner(System.in);
System.out.print("Enter the upperbound: ");
upperbound = in.nextInt();
for (int i = 1; i <= upperbound; i++) {
if (isPerfect(i)) { //boolean to check if number is a perfect number
perfNums.add(i);
}
}
System.out.println("Perfect numbers between 1 and " + upperbound + " are:");
for (int i = 0; i < perfNums.size(); i++) {
System.out.print(perfNums.get(i) + " = ");
printFactor((int)perfNums.get(i));
System.out.println();
}
Here's the printFactor class.
private static void printFactor(int number){
int factor = 1;
while(factor < number){
if (number%factor == 0) System.out.print(factor+ " + ");
//I don't know how to print the + sign otherwise.
factor++;
}
}
And here's a sample output:
Enter the upperbound: 10000
Perfect numbers between 1 and 10000 are:
6 = 1 + 2 + 3 +
28 = 1 + 2 + 4 + 7 + 14 +
496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248 +
8128 = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 127 + 254 + 508 + 1016 + 2032 + 4064 +
I've got the main gist of it but I've struggled with an output issue. Due to the restrictions of my online submission system, my output needs to fit exact specifications.
My question is how do I go about printing all the factors of my perfect number but removing the + sign at the end? (e.g)6 = 1 + 2 + 3
I'm not too sure of many methods to print from a while loop. Would a for-loop be better for my goals? Or are there alternative methods to print the factors of a number?
The least amount of change to address this might be something like this:
private static void printFactor(int number)
System.out.print(1);
int factor = 2;
while (factor<number) {
if (number%factor == 0) System.out.print(" + " + factor);
factor++;
}
}
1 is always a factor, so you can print that before the loop and then prepend + to every subsequent factor.
You should cache the output you want to print into a StringBuilder. Then you are able to remove the last plus sign before you print the whole String. It also has a better performance.
private static void printFactor(int number)
{
StringBuilder output = new StringBuilder();
int factor = 1;
while (factor < number)
{
if (number % factor == 0)
output.append(factor + " + ");
factor++;
}
// remove last plus sign
output.deleteCharAt(output.length() - 1);
// print the whole string
System.out.print(output.toString());
}
Since factor starts from value 1 and number % 1 == 0 will always be true, you might print 1 first and then flip factor and + in System.out.print. Like this:
private static void printFactor(int number) {
if(number > 0) {
System.out.print(1);
}
int factor = 2;
while (factor<number) {
if (number % factor == 0) {
System.out.print(" + " + factor);
}
factor++;
}
}
Not the best solution, but it will do the job.
Try to create a variable String numb and use substring method like this:
String numb ="";
while(factor<number){
if(number%factor == 0)
numb= numb + factor+ " + ";
factor++;
}
System.out.print(numb.substring(0, numb.trim().length()-1));
Just for the sake of using Java 8 :)
private static void printFactor(int number){
System.out.println(IntStream.range(1, number)
.filter(p -> number % p == 0)
.mapToObj(i -> String.valueOf(i))
.collect(Collectors.joining(" + ")));
}
Thanks everyone for the quick response. You all have been a lifesaver, and I managed to pick up some new things to consider when I code in the future.
Anyway, while waiting for a reply I was fiddling with the code and came up with a rather inelegant solution, if anybody's interested. Here's the changes to the main class:
System.out.println("Perfect numbers between 1 and " + upperbound + " are:");
for(int i=0; i<perfNums.size(); i++){
System.out.print(perfNums.get(i) + " = ");
outputString = printFactor2(perfNums.get(i));
if(outStr.endsWith(" + ")) outStr = outStr.substring(0, outStr.length()-3);
//because the submission system would cry foul with even a single extra space
System.out.println(outStr);
}
And here's the changes to the printFactor class:
private static String printFactor2(int number){
String out = "";
int factor = 1;
while(factor<number){
if(number%factor == 0) out += factor + " + ";
factor++;
}
return out;
}
Basically, what I did was append the factors to a string, then removing the trailing + sign using the substring method. On hindsight, I probably should've called the substring method inside the printFactor class instead. Something like return out.substring(0, out.length()-3); perhaps?
Nevertheless, thanks everyone!
String secondLine = ...E......E..E.E;
String failures = "E";
String passed = ".";
int i = 0;
while ((i = (secondLine.indexOf(failures, i) + 1)) > 0) {
System.out.println(i);
feedbackString += "<strong style='color: red;'><li>Failed: </strong><strong>" + i + "</strong> - " + "out of " + resultString.length() + " tests.<br>";
}
The total number of the tests is the sum of the dots which is = 12. and the E's are the failures which in this case = 4.
The dots are the passes and the E's are the failures. Whenever this is ran and there is a failure, it adds an 'E' in front of the dot which becomes'.E'. I can get the E's on its own but I want a statement that says given a dot comes before the E and then it should print the '.E' and pass it into a variable called failedTest.
The code above has an output of: 4, 11, 14, 16 which is not what I want as its considering each character separately but I want it to consider '.E' as one that is if an E comes after a dot then it should consider it as one. if this should be ran considering the '.E' as failure, the expected output should be 3, 9, 11, 12. Thanks :)
I understand your problem better now: if i am right, you print a ., ran the test and if it do not pass, you will print an E.
The point if the final length of secondLine is the number of test plus the number of error, so the if the first error is the test T-i, the T-i dot would be at the position T-i, its E would be at the position (T-1) + 1. The following test would be displaced one position: the dot of the test T-(i+1) would be at the position (T-i) + 2. Do you see the point?
So, this is my suggestion
String secondLine = "...E......E..E.E";
String failures = "E";
String passed = ".";
int detectedErrors = 0;
int i = 0;
while ((i = (secondLine.indexOf(failures, i) + 1)) > 0) {
System.out.println(i);
feedbackString += "<strong style='color: red;'><li>Failed: </strong><strong>"
+ (i - detectedErrors) // here
+ "</strong> - " + "out of " + resultString.length() + " tests.<br>";
detectedErrors += 1; // and here
}
You need to keep track of the number of extra characters in the secondLine and subtract them from the match position. Also change your failure String to ".E"
String secondLine = "...E......E..E.E";
String failures = ".E";
String passed = ".";
int n = 0;
int i = 0;
while ((i = (secondLine.indexOf(failures, i) + 1)) > 0) {
System.out.println(i-n);
n++;
feedbackString += "<strong style='color: red;'><li>Failed: </strong><strong>" + (i-n) + "</strong> - " + "out of " + resultString.length() + " tests.<br>";
This is what I have so far. I can't tell exactly how to change the numbers so it makes sense. Do I need to include the index as part of the equation? Although it seems like n1(the previous number) + (1/n2) should give me a new n2. Any thoughts?
package myrecursivemethod;
public class MyRecursiveMethod {
private static double index = 0;
private static double stoppingPoint=10;
public static void main(String[] args) {
double n1= 0;
double n2= 1;
System.out.println("index: " + index + "->" + n1 );
myRecursiveMethod(n1, n2);
}
public static void myRecursiveMethod(double n1, double n2)
{
System.out.println("index: " + index + " -> " + (n1+(1/n2)));
if (index == stoppingPoint)
return;
index ++;
myRecursiveMethod(n2, n1+(1/n2));
}
}
You need to take a look at your formula little closer and try to find a way to present this formula using similar formula with different arguments. For instance
sum(i) = 1 + 2 + 3 + 4 + ... + (i-1) + i
is same as
sum(i) = (1 + 2 + 3 + 4 + ... + (i-1)) + i
but since
1 + 2 + 3 + 4 + ... + (i-1) = sum(i-1)
we can rewrite entire formula as
sum(i) = sum(i-1) + i
(or actually)
{ sum(i-1) + i if i>0
sum(i) = {
{ 0 if i==0
Formula from your question is very similar to this one and can be presented in similar (recursive) way.
I have a text file with only +'s and blank spaces. i have to find a target within this file that looks like a spaceship. but the spaceship does not have to be perfect.
thanks in advance
this is the text file with the targets, a smaller version. there is at least 1 target in this.
+ ++ + + + + + + + +++ +
+ ++ + + ++ + + ++ ++ + +
+ + + + ++ + + ++++ ++
+ + ++++ + ++ + ++ +
+ + + + ++ + ++ + +
+ + + + ++ + + + +
+ + ++ + + +++ ++ +++
+ + + + ++ + ++ ++ + ++
+ + + + + ++ + + + + ++ + +
+ ++ + + ++ ++ +++ +
+ ++ + ++ + + + + ++ ++ +
+ + ++ ++ + + + + +
+ + + + + ++ + +
this is the target
+
+
+++
+++++++
++ ++
++ + ++
++ +++ ++
++ + ++
++ ++
+++++++
+++
I have tried Regex pattern reading but the file is too big so i decided to go against that. I do not know any other way to solve this.
I don't think you can or need to do anything really fancy here.
You can start by encoding your patterns. In this case, you could:
Encode every line as a string, and the lines themselves in an array: String[]
Encode every line as a string, and the lines themselves in an List: List<String>
Encode every line as a char[], and the lines themselves in an array: char[][]
Number 3 has the benefit that you can easily index it as a matrix:
char[][] matrix = ...;
char ch = matrix[row][column];
So you have:
char[][] search = new char[searchRows][searchColumns];
char[][] target = new char[targetRows][targetColumns];
You algorithm could be:
For every possible position that target could occur in search, calculate how many characters are equal
The position with the highest amount of equal characters wins
Get a percentage by dividing this amount of equal characters by the total amount of characters in target and you get a percentage
If the percentage is over a certain threshold, it's a match
Step1:
The maximum row or column is the total number of rows or columns in the search pattern minus the rows or columns in the target pattern.
int maxMatch = 0;
int maxMatchRow = -1;
int maxMatchColumn = -1;
for (int row = 0; row <= searchRows - targetRows; row++) {
for (int column = 0; columns <= searchColumns - targetColumns; column++) {
int match = calculateMatch(search, target, row, column);
if (match > maxMatch) {
maxMatchRow = row;
maxMatchColumn = column;
}
}
}
And to calculate matches in method calculateMatch, just add one if the characters in search and target are the same (but add offset row and column when you check search, not when you check target)
I think you should be able to finish it from there.