largest product of 30 consecutive digits - java

I was given a programming question by a friend where I was given a 1000 character string of numbers. The task is to find the largest product of 30 consecutive digits.
Although my code looks right, the answer seems to come out really low, why is this?
The relevant code for this problem has been provided below.
static String s = "2389748943892"; //... This number is actually 1000 characters.
public static void main(String[] args) {
// TODO Auto-generated method stub
int largest = 0;
for(int i = 0; i < 970; i ) {
String cur = s.substring(i, i 30);
int cur_val = 0;
for(int x = 0; x < 30; x ) {
if(x == 0) {
System.out.println(Integer.parseInt(cur.substring(0, 1)));
cur_val = Integer.parseInt(cur.substring(x, 1));
} else {
cur_val = cur_val * Integer.parseInt(cur.substring(x, x 1));
}
}
if(cur_val > largest) {
largest = cur_val;
}
System.out.println("Largest: " largest);
// should be 8876473335152640000 but is 2013265920
}
}

Edit: Arrgh, I read 'slow' instead of 'low'...
OK, forget about the performance issues, I thought you were speaking of.
Howver, long won't help you either: calculate ln(9^30)/ln(2), and you get little more than 95, thus you need 96 digits. Try Math.BigInteger then!
This is due to the excessive usage of substring (resulting in constructing and destroying new String objects all the time). As you are only interested in single characters, better use s.charAt(n). Parsing is then easy, too: Just subtract '0' from the char you got this way. So you get:
for(int i = 0; i < 970; ++i)
{
int cur_val = 0;
for(int x = i; x < i + 30; ++x)
{
cur_val *= s.charAt(x) - '0';
}
}
/* rest as you had already */
(OK, I left out printing the substring).
Additionally, in the code you posted, there are some syntax errors (substring i, i 30, apparently there is missing a '+') and you did not increment the counter variables (if this happened in your code, too, you would have ended in endless loops - but then you would not have gotten a slow result, you would not have gotten any at all).
You might include some short cuts (e. g. if you find a '0' in the outer loop, you know that the result for the next 30 iterations will be 0 and you could skip these), giving you another speedup.

Related

Multiplicative Sum Solver not functioning

In a class I am taking, we are supposed to solve equations that look like this ([] = digit):
[][]*[][][]=[][][][]
Where each digit 1-9 can only be used once.
The one the code I have made is solving is [][]*[][][]=4396
I have code that is free of errors, but will not do the intended action
Disclaimer: The code does not check if the digits 1-9 are only used once, that is up for the human to decide (for now, please do not add this function in any example code)
Here is the code:
public class MK1
{
public static void main(String[] args)
{
//the full sum
long sum = 4396;
long guess = 10000, guessCopy, otherSum = 0;
short count = 0;
//the digits used to guess the number
long[] digits = new long[5];
while(guess <= 99999)
{
//sets the different indexes of digits[] to the digits of guess
guessCopy = guess;
count = 0;
while(guessCopy > 0)
{
digits[count] = (guessCopy % 10);
guessCopy = guessCopy / 10;
count++;
}
//determining if the guess is correct
otherSum = ((digits[4]*10) + digits[3]) * ((digits[2]*100) + (digits[1]*10) + digits[0]);
if(otherSum == sum)
{
//Print out digits that work
for(int i = 0; i > digits.length; i++)
{
System.out.println(digits[i]);
//print out the separation between different solutions
if(i == digits.length -1)
{
System.out.println("next possible solution");
}
}
}
//iterating the guess
guess++;
}
}
}
For one, your digits are backwards in your otherSum calculation line. Also, your loop to print digits has the wrong comparison sign, it should be i < digits.length. Here is working code you should replace in:
//determining if the guess is correct
otherSum = ((digits[0]*10) + digits[1]) * ((digits[2]*100) + (digits[3]*10) + digits[4]);
if(otherSum == sum)
{
//Print out digits that work
for(int i = 0; i < digits.length; i++)
{
System.out.println(digits[i]);
//print out the separation between different solutions
if(i == digits.length -1)
{
System.out.println("next possible solution");
}
}
}
You might also want to consider switching your output to look better, right now its very vertical and tough to interpret.

Good fix for this algorithmic puzzle code (USACO)?

I'm a first-year computer science student and I am currently dabbling in some algorithmic competitions. The code below that I made has a flaw that I'm not sure how to fix
Here is the problem statement:
http://www.usaco.org/index.php?page=viewproblem2&cpid=811
In the statement, I missed where it said that Farmer John could only switch boots on tiles that both boots can stand on. I tried adding constraints in different places but none seemed to address the problem fully. I don't really see a way to do it without butchering the code
Basically, the problem is that John keeps switching boots on tiles where the new boots can't stand on, and I can't seem to fix it
Here is my code (sorry for the one letter variables):
import java.io.*;
import java.util.*;
public class snowboots {
static int n,k;
static int[] field,a,b; //a,b --> strength, distance
static int pos;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("snowboots.in"));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("snowboots.out")));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
k = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
field = new int[n];
a = new int[k];
b = new int[k];
for (int i = 0; i < n; i++)
field[i] = Integer.parseInt(st.nextToken());
for (int i = 0; i < k; i++) {
st = new StringTokenizer(br.readLine());
a[i] = Integer.parseInt(st.nextToken());
b[i] = Integer.parseInt(st.nextToken());
}
pw.println(solve());
pw.close();
}
static int solve() {
pos = 0;
int i = 0; //which boot are we on?
while(pos < n-1) {
while(move(i)); //move with boot i as far as possible
i++; //use the next boot
}
i--;
return i;
}
static boolean move(int c) {
for (int i = pos+b[c]; i > pos; i--) {
if (i < n && field[i] <= a[c]) { //snow has to be less than boot strength
pos = i;
return true;
}
}
return false;
}
}
I tried adding a constraint in the "move" method, and one when updating I, but they both are too strict and activate at unwanted times
Is it salvageable?
Yes, it's possible to salvage your solution, by adding an extra for-loop.
What you need to do is, if you find that your previous pair of boots can get you all the way to a tile that's too deep in snow for your next pair, then you need to try "backtracking" to the latest tile that's not too deep. This ends up giving a solution in worst-case O(N·B) time and O(1) extra space.
It may not be obvious why it's OK to backtrack to that tile — after all, just because you can reach a given tile, that doesn't necessarily mean that you were able to reach all the tiles before it — so let me explain a bit why it is OK.
Let maxReachableTileNum be the number (between 1 and N) of the last tile that you were able to reach with your previous boots, and let lastTileNumThatsNotTooDeep be the number (between 1 and N) of the last tile on or before maxReachableTileNum that's not too deeply snow-covered for your next pair. (We know that there is such a tile, because tile #1 has no snow at all, so if nothing else we know that we can backtrack to the very beginning.) Now, since we were able to get to maxReachableTileNum, then some previous boot must have either stepped on lastTileNumThatsNotTooDeep (in which case, no problem, it's reachable) or skipped over it to some later tile (on or before maxReachableTileNum). But that later tile must be deeper than lastTileNumThatsNotTooDeep (because that later tile's depth is greater than scurrentBootNum, which is at least at great as the depth of lastTileNumThatsNotTooDeep), which means that the boot that skipped over lastTileNumThatsNotTooDeep certainly could have stepped on lastTileNumThatsNotTooDeep instead: it would have meant taking a shorter step (OK) onto a less-deeply-covered tile (OK) than what it actually did. So, either way, we know that lastTileNumThatsNotTooDeep was reachable. So it's safe for us to try backtracking to lastTileNumThatsNotTooDeep. (Note: the below code uses the name reachableTileNum instead of lastTileNumThatsNotTooDeep, because it continues to use the reachableTileNum variable for searching forward to find reachable tiles.)
However, we still have to hold onto the previous maxReachableTileNum: backtracking might turn out not to be helpful (because it may not let us make any further forward progress than we already have), in which case we'll just discard these boots, and move on to the next pair, with maxReachableTileNum at its previous value.
So, overall, we have this:
public static int solve(
final int[] tileSnowDepths, // tileSnowDepths[0] is f_1
final int[] bootAllowedDepths, // bootAllowedDepths[0] is s_1
final int[] bootAllowedTilesPerStep // bootAllowedTilesPerStep[0] is d_1
) {
final int numTiles = tileSnowDepths.length;
final int numBoots = bootAllowedDepths.length;
assert numBoots == bootAllowedTilesPerStep.length;
int maxReachableTileNum = 1; // can reach tile #1 even without boots
for (int bootNum = 1; bootNum <= numBoots; ++bootNum) {
final int allowedDepth = bootAllowedDepths[bootNum-1];
final int allowedTilesPerStep = bootAllowedTilesPerStep[bootNum-1];
// Find the starting-point for this boot -- ideally the last tile
// reachable so far, but may need to "backtrack" if that tile is too
// deep; see explanation above of why it's safe to assume that we
// can backtrack to the latest not-too-deep tile:
int reachableTileNum = maxReachableTileNum;
while (tileSnowDepths[reachableTileNum-1] > allowedDepth) {
--reachableTileNum;
}
// Now see how far we can go, updating both maxReachableTileNum and
// reachableTileNum when we successfully reach new tiles:
for (int tileNumToTry = maxReachableTileNum + 1;
tileNumToTry <= numTiles
&& tileNumToTry <= reachableTileNum + allowedTilesPerStep;
++tileNumToTry
) {
if (tileSnowDepths[tileNumToTry-1] <= allowedDepth) {
maxReachableTileNum = reachableTileNum = tileNumToTry;
}
}
// If we've made it to the last tile, then yay, we're done:
if (maxReachableTileNum == numTiles) {
return bootNum - 1; // had to discard this many boots to get here
}
}
throw new IllegalArgumentException("Couldn't reach last tile with any boot");
}
(I tested this on USACO's example data, and it returned 2, as expected.)
This can potentially be optimized further, e.g. with logic to skip pairs of boots that clearly aren't helpful (because they're neither stronger nor more agile than the previous successful pair), or with an extra data structure to keep track of the positions of latest minima (to optimize the backtracking process), or with logic to avoid backtracking further than is conceivably useful; but given that N·B ≤ 2502 = 62,500, I don't think any such optimizations are warranted.
Edited to add (2019-02-23): I've thought about this further, and it occurs to me that it's actually possible to write a solution in worst-case O(N + B log N) time (which is asymptotically better than O(N·B)) and O(N) extra space. But it's much more complicated; it involves three extra data-structures (one to keep track of the positions of latest minima, to allow backtracking in O(log N) time; one to keep track of the positions of future minima, to allow checking in O(log N) time if the backtracking is actually helpful (and if so to move forward to the relevant minimum); and one to maintain the necessary forward-looking information in order to let the second one be maintained in amortized O(1) time). It's also complicated to explain why that solution is guaranteed to be within O(N + B log N) time (because it involves a lot of amortized analysis, and making a minor change that might seem like an optimization — e.g., replacing a linear search with a binary search — can break the analysis and actually increase the worst-case time complexity. Since N and B are both known to be at most 250, I don't think all the complication is worth it.
You can solve this problem by Dynamic Programming. You can see the concept in this link (Just read the Computer programming part).
It has following two steps.
First solve the problem recursively.
Memoize the states.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mx 100005
#define mod 1000000007
int n, b;
int f[333], s[333], d[333];
int dp[251][251];
int rec(int snowPos, int bootPos)
{
if(snowPos == n-1){
return 0;
int &ret = dp[snowPos][bootPos];
if(ret != -1) return ret;
ret = 1000000007;
for(int i = bootPos+1; i<b; i++)
{
if(s[i] >= f[snowPos]){
ret = min(ret, i - bootPos + rec(snowPos, i));
}
}
for(int i = 1; i<=d[bootPos] && snowPos+i < n; i++){
if(f[snowPos + i] <= s[bootPos]){
ret = min(ret, rec(snowPos+i, bootPos));
}
}
return ret;
}
int main()
{
freopen("snowboots.in", "r", stdin);
freopen("snowboots.out", "w", stdout);
scanf("%d %d", &n, &b);
for(int i = 0; i<n; i++)
scanf("%d", &f[i]);
for(int i = 0; i<b; i++){
scanf("%d %d", &s[i], &d[i]);
}
memset(dp, -1, sizeof dp);
printf("%d\n", rec(0, 0));
return 0;
}
This is my solution to this problem (in C++).
This is just a recursion. As problem says,
you can change boot, Or
you can do a jump by current boot.
Memoization part is done by the 2-Dimensional array dp[][].
One way which to solve it using BFS. You may refer below code for details. Hope this helps.
import java.util.*;
import java.io.*;
public class SnowBoots {
public static int n;
public static int[] deep;
public static int nBoots;
public static Boot[] boots;
public static void main(String[] args) throws Exception {
// Read the grid.
Scanner stdin = new Scanner(new File("snowboots.in"));
// Read in all of the input.
n = stdin.nextInt();
nBoots = stdin.nextInt();
deep = new int[n];
for (int i = 0; i < n; ++i) {
deep[i] = stdin.nextInt();
}
boots = new Boot[nBoots];
for (int i = 0; i < nBoots; ++i) {
int d = stdin.nextInt();
int s = stdin.nextInt();
boots[i] = new boot(d, s);
}
PrintWriter out = new PrintWriter(new FileWriter("snowboots.out"));
out.println(bfs());
out.close();
stdin.close();
}
// Breadth First Search Algorithm [https://en.wikipedia.org/wiki/Breadth-first_search]
public static int bfs() {
// These are all valid states.
boolean[][] used = new boolean[n][nBoots];
Arrays.fill(used[0], true);
// Put each of these states into the queue.
LinkedList<Integer> q = new LinkedList<Integer>();
for (int i = 0; i < nBoots; ++i) {
q.offer(i);
}
// Usual bfs.
while (q.size() > 0) {
int cur = q.poll();
int step = cur / nBoots;
int bNum = cur % nBoots;
// Try stepping with this boot...
for (int i = 1; ((step + i) < n) && (i <= boots[bNum].maxStep); ++i) {
if ((deep[step+i] <= boots[bNum].depth) && !used[step+i][bNum]) {
q.offer(nBoots * (step + i) + bNum);
used[step + i][bNum] = true;
}
}
// Try switching to another boot.
for (int i = bNum + 1; i < nBoots; ++i) {
if ((boots[i].depth >= deep[step]) && !used[step][i]) {
q.offer(nBoots * step + i);
used[step][i] = true;
}
}
}
// Find the earliest boot that got us here.
for (int i = 0; i < nBoots; ++i) {
if (used[n - 1][i]) {
return i;
}
}
// Should never get here.
return -1;
}
}
class Boot {
public int depth;
public int maxStep;
public Boot(int depth, int maxStep) {
this.depth = depth;
this.maxStep = maxStep;
}
}

O(log n) Programming

I am trying to prepare for a contest but my program speed is always dreadfully slow as I use O(n). First of all, I don't even know how to make it O(log n), or I've never heard about this paradigm. Where can I learn about this?
For example,
If you had an integer array with zeroes and ones, such as [ 0, 0, 0, 1, 0, 1 ], and now you wanted to replace every 0 with 1 only if one of it's neighbors has the value of 1, what is the most efficient way to go about doing if this must occur t number of times? (The program must do this for a number of t times)
EDIT:
Here's my inefficient solution:
import java.util.Scanner;
public class Main {
static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
int n;
long t;
n = input.nextInt();
t = input.nextLong();
input.nextLine();
int[] units = new int[n + 2];
String inputted = input.nextLine();
input.close();
for(int i = 1; i <= n; i++) {
units[i] = Integer.parseInt((""+inputted.charAt(i - 1)));
}
int[] original;
for(int j = 0; j <= t -1; j++) {
units[0] = units[n];
units[n + 1] = units[1];
original = units.clone();
for(int i = 1; i <= n; i++) {
if(((original[i - 1] == 0) && (original[i + 1] == 1)) || ((original[i - 1] == 1) && (original[i + 1] == 0))) {
units[i] = 1;
} else {
units[i] = 0;
}
}
}
for(int i = 1; i <= n; i++) {
System.out.print(units[i]);
}
}
}
This is an elementary cellular automaton. Such a dynamical system has properties that you can use for your advantages. In your case, for example, you can set to value 1 every cell at distance at most t from any initial value 1 (cone of light property). Then you may do something like:
get a 1 in the original sequence, say it is located at position p.
set to 1 every position from p-t to p+t.
You may then take as your advantage in the next step that you've already set position p-t to p+t... This can let you compute the final step t without computing intermediary steps (good factor of acceleration isn't it?).
You can also use some tricks as HashLife, see 1.
As I was saying in the comments, I'm fairly sure you can keep out the array and clone operations.
You can modify a StringBuilder in-place, so no need to convert back and forth between int[] and String.
For example, (note: This is on the order of an O(n) operation for all T <= N)
public static void main(String[] args) {
System.out.println(conway1d("0000001", 7, 1));
System.out.println(conway1d("01011", 5, 3));
}
private static String conway1d(CharSequence input, int N, long T) {
System.out.println("Generation 0: " + input);
StringBuilder sb = new StringBuilder(input); // Will update this for all generations
StringBuilder copy = new StringBuilder(); // store a copy to reference current generation
for (int gen = 1; gen <= T; gen++) {
// Copy over next generation string
copy.setLength(0);
copy.append(input);
for (int i = 0; i < N; i++) {
conwayUpdate(sb, copy, i, N);
}
input = sb.toString(); // next generation string
System.out.printf("Generation %d: %s\n", gen, input);
}
return input.toString();
}
private static void conwayUpdate(StringBuilder nextGen, final StringBuilder currentGen, int charPos, int N) {
int prev = (N + (charPos - 1)) % N;
int next = (charPos + 1) % N;
// **Exactly one** adjacent '1'
boolean adjacent = currentGen.charAt(prev) == '1' ^ currentGen.charAt(next) == '1';
nextGen.setCharAt(charPos, adjacent ? '1' : '0'); // set cell as alive or dead
}
For the two samples in the problem you posted in the comments, this code generates this output.
Generation 0: 0000001
Generation 1: 1000010
1000010
Generation 0: 01011
Generation 1: 00011
Generation 2: 10111
Generation 3: 10100
10100
The BigO notation is a simplification to understand the complexity of the Algorithm. Basically, two algorithms O(n) can have very different execution times. Why? Let's unroll your example:
You have two nested loops. The outer loop will run t times.
The inner loop will run n times
For each time the loop executes, it will take a constant k time.
So, in essence your algorithm is O(k * t * n). If t is in the same order of magnitude of n, then you can consider the complexity as O(k * n^2).
There is two approaches to optimize this algorithm:
Reduce the constant time k. For example, do not clone the whole array on each loop, because it is very time consuming (clone needs to do a full array loop to clone).
The second optimization in this case is to use Dynamic Programing (https://en.wikipedia.org/wiki/Dynamic_programming) that can cache information between two loops and optimize the execution, that can lower k or even lower the complexity from O(nˆ2) to O(n * log n).

All digits in int are divisible by certain int

I am trying to figure out how to count all numbers between two ints(a and b), where all of the digits are divisible with another int(k) and 0 counts as divisible.Here is what I've made so far, but it is looping forever.
for (int i = a; i<=b; i++){
while (i < 10) {
digit = i % 10;
if(digit % k == 0 || digit == 0){
count ++;
}
i = i / 10;
}
}
Also I was thinking about comparing if all of the digits were divisible by counting them and comparing with number of digits int length = (int)Math.Log10(Math.Abs(number)) + 1;
Any help would be appreciated. Thank you!
Once you get in to your while block you're never going to get out of it. The while condition is when i less than 10. You're dividing i by 10 at the end of the whole block. i will never have a chance of getting above 10.
Try this one
public class Calculator {
public static void main(String[] args) {
int a = 2;
int b = 150;
int k = 3;
int count = 0;
for (int i = a; i <= b; i++) {
boolean isDivisible = true;
int num = i;
while (num != 0) {
int digit = num % 10;
if (digit % k != 0) {
isDivisible = false;
break;
}
num /= 10;
}
if (isDivisible) {
count++;
System.out.println(i+" is one such number.");
}
}
System.out.println("Total " + count + " numbers are divisible by " + k);
}
}
Ok, so there are quite a few things going on here, so we'll take this a piece at a time.
for (int i = a; i <= b; i++){
// This line is part of the biggest problem. This will cause the
// loop to skip entirely when you start with a >= 10. I'm assuming
// this is not the case, as you are seeing an infinite loop - which
// will happen when a < 10, for reasons I'll show below.
while (i < 10) {
digit = i % 10;
if(digit % k == 0 || digit == 0){
count ++;
// A missing line here will cause you to get incorrect
// results. You don't terminate the loop, so what you are
// actually counting is every digit that is divisible by k
// in every number between a and b.
}
// This is the other part of the biggest problem. This line
// causes the infinite loop because you are modifying the
// variable you are using as the loop counter. Mutable state is
// tricky like that.
i = i / 10;
}
}
It's possible to re-write this with minimal changes, but there are some improvements you can make that will provide a more readable result. This code is untested, but does compile, and should get you most of the way there.
// Extracting this out into a function is often a good idea.
private int countOfNumbersWithAllDigitsDivisibleByN(final int modBy, final int start, final int end) {
int count = 0;
// I prefer += to ++, as each statement should do only one thing,
// it's easier to reason about
for (int i = start; i <= end; i += 1) {
// Pulling this into a separate function prevents leaking
// state, which was the bulk of the issue in the original.
// Ternary if adds 1 or 0, depending on the result of the
// method call. When the methods are named sensibly, I find
// this can be more readable than a regular if construct.
count += ifAllDigitsDivisibleByN(modBy, i) ? 1 : 0;
}
return count;
}
private boolean ifAllDigitsDivisibleByN(final int modBy, final int i) {
// For smaller numbers, this won't make much of a difference, but
// in principle, there's no real reason to check every instance of
// a particular digit.
for(Integer digit : uniqueDigitsInN(i)) {
if ( !isDigitDivisibleBy(modBy, digit) ) {
return false;
}
}
return true;
}
// The switch to Integer is to avoid Java's auto-boxing, which
// can get expensive inside of a tight loop.
private boolean isDigitDivisibleBy(final Integer modBy, final Integer digit) {
// Always include parens to group sub-expressions, forgetting the
// precedence rules between && and || is a good way to introduce
// bugs.
return digit == 0 || (digit % modBy == 0);
}
private Set<Integer> uniqueDigitsInN(final int number) {
// Sets are an easy and efficient way to cull duplicates.
Set<Integer> digitsInN = new HashSet<>();
for (int n = number; n != 0; n /= 10) {
digitsInN.add(n % 10);
}
return digitsInN;
}

Checksums - ISBN program

This problem has me puzzled. I tried using a loop like this: Basically I tried to get the first digit from the input and do the formula but it doesn't seem to work. It looks so simple but I can't figure it out. Could you help me? Thanks.
public static int ISBN(String ninedigitNum) {
number = 9;
while (number > 0) {
int nextDigit = ninedigitNum.substring(0,1);
...
}
Checksums (Source: Princeton University). The International Standard
Book Number (ISBN) is a 10 digit code that uniquely specifies a book.
The rightmost digit is a checksum digit which can be uniquely
determined from the other 9 digits from the condition that d1 + 2d2 +
3d3 + ... + 10d10 must be a multiple of 11 (here di denotes the ith
digit from the right). The checksum digit d1 can be any value from 0
to 10: the ISBN convention is to use the value X to denote 10.
Example: the checksum digit corresponding to 020131452 is 5 since is
the only value of d1 between 0 and and 10 for which d1 + 2*2 + 3*5 +
4*4 + 5*1 + 6*3 + 7*1 + 8*0 + 9*2 + 10*0 is a multiple of 11. Create a
Java method ISBN() that takes a 9-digit integer as input, computes the
checksum, and returns the 10-digit ISBN number. Create 3 JUnit test
cases to test your method.
I got it, thanks a lot everyone!
What about it isn't working? Either way, I believe what you're missing is that you're continually getting the same substring, which will be the first number of the string: int nextDigit = ninedigitNum.substring(0,1);. In addition, you're going to want to use an int, not a String; you can technically convert from String to int if desired, but the problem itself calls for an int.
There are two ways to do this that jump to mind. I would do this by realizing that mod in powers of 10 will give you the respective digit of an integer, but the easier way is to convert to a char array and then access directly. Note that there's no error checking here; you'll have to add that yourself. In addition, there are a LOT of 'magic numbers' here: good code typically has very, very few. I would recommend learning more data structures before attempting problems like these; to be honest there's very few things you can do without at least arrays and linked lists.
char[] ISBN = ninedigitNum.toCharArray();
//Process each number
int total = 0;
for(int i=0; i<9; i++){
int current_int = Integer.parseInt(ISBN[i]);
total += current_int * (10 - i)
}
//Find value of d1
for(int i=0; i<9; i++){
if(((total + i) % 11) == 0){
total += i*100000000;
break;
}
}
return total;
In general: Use print outs with System.out.println(x); or use your compiler's debugger to see what's going on during processing.
So,
This is the piece of code that I wrote. I still think it could be made more efficient.
public class Problem3 {
public static String ISBN(String x)
{
char[]temp = x.toCharArray();
int counter = 2;
int sum = 0;
int j=0;
for(int i=8;i>=0;i--)
{
sum+= counter*Integer.parseInt(""+temp[i]);
counter+=1;
}
for(j=0;j<10;j++)
{
if((sum+j)%11==0)
{
break;
}
}
return x+""+j;
}
public static void main(String args[])
{
String a = "020131452";
System.out.println(ISBN(a));
}
}
Hope this helps.
This works:
public static int ISBN(String nineDigitNum){
int sum = 0;
for(int i = 0; i<nineDigitNum.length(); i++){
sum += Integer.parseInt(""+nineDigitNum.charAt(i))*(10-i);
}
return (sum%11);
}
Also I believe if the checksum is == to 10, it should return an X, so you could either change the return type and add an if statement somewhere, or just put the if statement outside wherever you are using this method.
Here is a short one without loops that uses only substring(), charAt() and length():
public static String ISBN(String nineDigits) {
int chkD = 11 - checkDigit(nineDigits, 0);
return nineDigits + ((chkD == 10) ? "X" : chkD);
}
public static int checkDigit(String nDsub, int chkD) {
if (nDsub.length() == 0)
return 0;
chkD = ((nDsub.charAt(0) - '0') * (nDsub.length() + 1));
return (chkD + checkDigit(nDsub.substring(1), chkD)) % 11;
}
Output:
> ISBN("123456789")
"123456789X"
> ISBN("123456780")
"1234567806"

Categories

Resources