Simple assembly code conversion to Java - java

I want to convert the following code into Java code. I think it is assembly code, but not sure. The part that I really do not get is y -= m < 3;.
int dow(int y, int m, int d)
{
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}

The boolean m < 3 will evaluate to 0 or 1. Then the operation y -= makes more sense.
In java, it would look more like:
y -= (m<3 ? 1 : 0)

That's C code, and I believe this
static final int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4,
6, 2, 4 };
static int dow(int y, int m, int d) {
if (m < 3) {
y--;
}
return (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
}
is equivalent. Because y -= m < 3; will evaluate to y-=1; if m<3 otherwise y-=0;. Instead you can use a simple if. Finally the t[] can't be static in a method in Java.

You code in Java would be
public static void main(String[] args){
int calculated_value = dow(2014, 7, 31);
}
public static int dow(int y, int m, int d){
int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= (m < 3 ? 1 : 0);
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}

I see that you already have a few good literal translations of the code in other answers, but what you really want to write is the following, which is clear, readable, and relies on a trusted library:
public static int dow(int y, int m, int d)
{
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, y);
c.set(Calendar.MONTH, m - 1);
c.set(Calendar.DAY_OF_MONTH, d);
return (c.get(Calendar.DAY_OF_WEEK) - 1);
}
The - 1 at the end is only to map the numeric day-of-week representation that Java uses (where Sunday=1 and Saturday=7) to the same mappings as in the original code. Similar with the m - 1 too.

Here is my conversion to Java:
package datecalculator;
import javax.swing.*;
public class DateCalculator {
public static int calculateDay(int y, int m, int d){
//Tomohiko Sakamoto's method
int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= (m < 3 ? 1 : 0);
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
public static void main(String[] args){
//Receiving input
int y = Integer.parseInt(JOptionPane.showInputDialog("Enter the year"));
int m = Integer.parseInt(JOptionPane.showInputDialog("Enter the month"));
int d = Integer.parseInt(JOptionPane.showInputDialog("Enter the day"));
//Calling Tomohiko Sakamoto's method
int answer = calculateDay(y, m, d);
//Output
if (answer == 0){JOptionPane.showMessageDialog(null, "Sunday");}
if (answer == 1){JOptionPane.showMessageDialog(null, "Monday");}
if (answer == 2){JOptionPane.showMessageDialog(null, "Tuesday");}
if (answer == 3){JOptionPane.showMessageDialog(null, "Wednesday");}
if (answer == 4){JOptionPane.showMessageDialog(null, "Thursday");}
if (answer == 5){JOptionPane.showMessageDialog(null, "Friday");}
if (answer == 6){JOptionPane.showMessageDialog(null, "Saturday");}
}
}

Related

Small exercise for Java given two arrays which represents a path

Given two arrays which represents a path and each element in the array represent the time it takes the driver to travel, write a method that chooses the fastest path he can take. The driver can switch paths only once between arrays.
For example the following arrays:
int[] road1 = new int[] { 5, 4, 5, 8, 12, 9, 9, 3 };
int[] road2 = new int[] { 7, 3, 3, 12, 10, 2, 10, 7 };
the output should be 49 since the driver will start at road2 and switch at index 6 to the second Array.
Edit:
My question is how do I make the recursion stop after switching to the other array? I tried to put a counter marker but it didn't work and I reverted back to my original output. Am I missing something about how recursion works?
My code prints 53 where it should print 49.
My code:
public class MyClass {
public static int shortestRoad(int[] road1, int[] road2) {
return shortestRoadNumbers(road1, road2, 0);
}
private static int shortestRoadNumbers(int[] road1, int[] road2, int index) {
if (index == road1.length || index == road2.length) {
return 0;
}
if (road1[index] >= road2[index] && road1[index + 2] >= road2[index + 2]) {
return (road2[index] + shortestRoadNumbers(road1, road2, index + 1));
} else {
return (road1[index] + shortestRoadNumbers(road1, road2, index + 1));
}
}
public static void main(String args[]) {
int[] road1 = new int[] { 5, 4, 5, 8, 12, 9, 9, 3 };
int[] road2 = new int[] { 7, 3, 3, 12, 10, 2, 10, 7 };
MyClass.shortestRoad(road1, road2);
int result = MyClass.shortestRoad(road1, road2);
System.out.println(result);
}
}
Let the following schema to illustrate your problem
We have two paths, and each path contain many nodes (values) , we can switch from one path to another just one time. Find the best combination of nodes (values) that minimise the score.
We can distinguish 4 cases:
1- the sum of the values of the first path without switching.
2-the sum of the values of the second path without switching.
3-the sum of the values from the first path until a node i, then switch to path second path from node i+1 (sum from node+1 til the end)
4-the inverse of the point 3.
static int shortestRoad(int road1[], int road2[])
{
// case 1
int bestValue = sumValues(road1,0);
// case 2
int sumValuesRoad2 = sumValues(road2,0);
if ( sumValuesRoad2 < bestValue)
bestValue = sumValuesRoad2;
// case 3: best values of all combination from road 1 to road 2
int bestValuesSwitchFromRoad1ToRoad2 = shortestRoad_Switch_RoadFrom_RoadTo(road1, road2);
if ( bestValuesSwitchFromRoad1ToRoad2 < bestValue)
bestValue = bestValuesSwitchFromRoad1ToRoad2;
// case 4: best values of all combination from road 2 to road 1
int bestValuesSwitchFromRoad2ToRoad1 = shortestRoad_Switch_RoadFrom_RoadTo(road2, road1);
if ( bestValuesSwitchFromRoad2ToRoad1 < bestValue)
bestValue = bestValuesSwitchFromRoad2ToRoad1;
return bestValue;
}
sum the values of a given array from idx til the end:
static int sumValues(int array[], int idx_from)
{
int sum = 0;
for (int i = idx_from; i<array.length; ++i)
sum += array[i];
return sum;
}
case 3 and 4:
static int shortestRoad_Switch_RoadFrom_RoadTo(int[] road_from, int[] road_to)
{
int sumValues_RoadFrom_til_idx = 0;
int sumValues_RoadFrom_idx_switch_RoadTo = 0;
int bestValue = Integer.MAX_VALUE;
for (int i = 0; i<road_from.length-1; ++i)
{
sumValues_RoadFrom_til_idx += road_from[i];
sumValues_RoadFrom_idx_switch_RoadTo = sumValues_RoadFrom_til_idx+sumValues(road_to,i+1);
if(sumValues_RoadFrom_idx_switch_RoadTo < bestValue )
bestValue = sumValues_RoadFrom_idx_switch_RoadTo;
}
return bestValue;
}
Driver code:
public static void main(String[] args)
{
int road1[] = { 5, 4, 5, 8, 12, 9, 9, 3 };
int road2[] = { 7, 3, 3, 12, 10, 2, 10, 7 };
int road_a[] = { 1, 1, 1, 1, 1, 9, 9, 9,9,9 };
int road_b[] = { 9, 9, 9, 9, 9, 1, 1, 1,1,1 };
int road_c[] = { 1, 1, 1, 1, 1, 2 };
int road_d[] = { 9, 9, 9, 9, 9, 1, 1, 1,1,1 };
System.out.println("best road1, road2 = "+shortestRoad(road1,road2));
System.out.println("best road_a, road_b = "+shortestRoad(road_a,road_b));
System.out.println("best road_c, road_d = "+shortestRoad(road_c,road_d));
return 0;
}
Results:
best road1, road2 = 49
best road_a, road_b = 10
best road_c, road_d = 7
ps:
the best path in your example is begin from road2 and then switch to road 1 at i=5 (i begin from 0)
{ 5, 4, 5, 8, 12, 9, -->9, 3 }
{ -->7, 3, 3, 12, 10, 2 /, 10, 7 }
public static int shortestRoad(int[]road1, int[]road2)
{
int sumRoad1Only = 0;
int sumRoad2Only = 0;
for(int i=0; i<road1.length; i++)
{
sumRoad1Only += road1[i];
sumRoad2Only += road2[i];
}
Those sums are for the option that the driver chooses one lane, and doesn't change it until the end. Now, we can find the switch index, for options like starting at one road, and switching to the other. In this specific question I realized that the best point of switch between the arrays - is where the difference between the two collected sums until a certain index is the largest. In your example, it is index 6. That doesn't say that switching a lane is always giving a smaller sum.
int roadIndex1 = road1.length-1;
int roadIndex2 = road2.length-1;
int totalSumRoad1 = sumRoad1Only;
int totalSumRoad2 = sumRoad2Only;
int max = 0;
int indexOfSwitch = 0;
int diff = 0;
while(roadIndex1 >=0 && roadIndex2 >=0)
{
diff = Math.abs(totalSumRoad2 - totalSumRoad1);
if(diff > max)
{
max = diff;
indexOfSwitch = roadIndex1;
}
totalSumRoad1 -= road1[roadIndex1];
totalSumRoad2 -= road2[roadIndex2];
roadIndex1--;
roadIndex2--;
}
If the index of switch is at last index, we shall move it one left, so there be a transition between the arrays.
if(indexOfSwitch == road1.length-1)
{
indexOfSwitch--;
}
now we found the indexOfSwitch, we can calculate the options of starting at road1, and switching exactly once to road2, and vice versa:
int begin1 = 0;
int begin2 = 0;
for(int k = 0; k<=indexOfSwitch; k++)
{
begin1 += road1[k];
begin2 += road2[k];
}
int end1 = sumRoad1Only - begin1;
int end2 = sumRoad2Only - begin2;
int begin1End2 = begin1 + end2;
int begin2End1 = begin2 + end1;
and when we find all the options, we can return the minimum.
return Math.min(Math.min(sumRoad1Only, sumRoad2Only), Math.min(begin1End2, begin2End1));

Array left rotation in Java

Given an array of integers and a number, I need to perform left rotations on the array and return the updated array to be printed as a single line of space-separated integers.
I pass 7/9 checks, but some with large arrays fail because of time-out.
The time has to be <= 4 sec.
static int[] rotLeft(int[] a, int d) {
int x = 0;
while (x != d) {
int first = a[0];
int last = a[a.length - 1];
for (int i = 0; i < a.length - 1; i++) {
a[i] = a[i + 1];
if (i == a.length - 2)
a[a.length - 2] = last;
a[a.length - 1] = first;
}
x++;
}
return a;
}
you're rotating only one position at a time, it is very slow, it is better to shift elements to appropriate places, for example:
static int[] rotLeft(int[] a, int d) {
if (d == 0 || a == null || a.length == 0) {
return a;
}
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[(i + d) % a.length];
}
return b;
}
There are two things you could apply to this problem to improve the runtime.
Ensure that d is less than a.length. If d is greater than a.length, then you are rotating elements past their original position and wasting cycles. An easy way to achieve this is with the modulus assignment operator (i.e., d %= a.length, which is equivalent to d = d % a.length).
Elements should be shifted by the whole distance we are rotating, rather than shifting by one space each time. This allows us to perform the entire operation is 1 action, instead of in d action(s).
Applying these two principles would give us the following code:
static int[] rotLeft(int[] a, int d) {
if (d < 0) {
d = a.length - (-d % a.length);
}
d %= a.length;
if (d == 0) {
return a;
}
int first = a[0];
int i = 0;
int position = 0;
while (i < a.length) {
a[position] = a[(position + d) % a.length];
position = (position + d) % a.length;
i++;
}
a[a.length - d] = first;
return a;
}
You make multiple passes, each time rotating by one place, which makes your program slow.
There are at least 3 approaches to improve your program:
allocate a new array and put elements in appropriate locations, instead of rotating in place
use a buffer to store d elements while rotating others in place
use a juggling algorithm https://www.google.com/amp/s/www.geeksforgeeks.org/array-rotation/amp/
The third option performs rotation in place.
It may be worthwhile to microbenchmark all 3 to compare the speed for different input sizes
Of course you can repeat the rotation d times as you did in your sample code. But much faster would be if you would calculate the shift and do it in one go:
import static java.lang.System.*;
static int[] rotLeft( int[] a, int d )
{
var len = a.length;
var shift = d % len;
var buffer = new int[len];
arraycopy( a, shift, buffer, 0, len - shift );
arraycopy( a, 0, buffer, len - shift, shift );
arraycopy( buffer, 0, a, 0, len );
return a;
}
Of course, instead of System.arraycopy() you can use a for-loop. If you are not forced to return a, you can omit the third call to arraycopy() and return buffer instead; this would leave the original array unchanged, too.
To output the array, try this:
var joiner = new StringJoiner( " " );
for( var v : a ) joiner.add( Integer.toString( v ) );
System.out.println( joiner.toString() );
For better performance, you should use the built-in array copy methods.
If you have to update the existing array, like your code is doing, I'd recommend doing it like this:
static int[] rotLeft(int[] a, int d) {
if (a == null || a.length <= 1)
return a; // nothing to rotate
int shift = (d % a.length + a.length) % a.length; // normalize d
if (shift == 0)
return a; // no or full rotation(s)
int[] t = Arrays.copyOfRange(a, 0, shift);
System.arraycopy(a, shift, a, 0, a.length - shift);
System.arraycopy(t, 0, a, a.length - shift, shift);
return a;
}
If the returned array must be different, like this other answers do, I'd do it like this:
static int[] rotLeft(int[] a, int d) {
if (a == null || a.length <= 1)
return Arrays.copyOf(a, a.length); // nothing to rotate
int shift = (d % a.length + a.length) % a.length; // normalize d
if (shift == 0)
return Arrays.copyOf(a, a.length); // no or full rotation(s)
int[] t = new int[a.length];
System.arraycopy(a, shift, t, 0, a.length - shift);
System.arraycopy(a, 0, t, a.length - shift, shift);
return t;
}
Both of the above solution allow d to exceed the size of the array, i.e. do more than a full rotation, and to use negative values, i.e. rotate right instead of left.
Test
System.out.println(Arrays.toString(rotLeft(new int[] { 1, 2, 3, 4, 5 }, 1)));
System.out.println(Arrays.toString(rotLeft(new int[] { 1, 2, 3, 4, 5 }, 3)));
System.out.println(Arrays.toString(rotLeft(new int[] { 1, 2, 3, 4, 5 }, 5)));
System.out.println(Arrays.toString(rotLeft(new int[] { 1, 2, 3, 4, 5 }, 7)));
System.out.println(Arrays.toString(rotLeft(new int[] { 1, 2, 3, 4, 5 }, -7)));
Output
[2, 3, 4, 5, 1]
[4, 5, 1, 2, 3]
[1, 2, 3, 4, 5]
[3, 4, 5, 1, 2]
[4, 5, 1, 2, 3]
You don't have to do the rotations one by one. If you rotate by d, the element at index i moves to index i - d when i >= d, and into index N + i - d when i < d. Makes sense?
int[] result = new int[a.length]
for (int i = 0; i < a.length; i++) {
if (i < d) {
result[a.length + i - d] = a[i];
} else {
result[i - d] = a[i];
}
}
return result;
To handle the case where d >= a.length, you can add d = d % a.length as a pre-processing step.

How do I get all ways to divide a number in multiple numbers?

I want to divide a number x into y pieces and I want all possible configurations to do this. How can I do this efficiently?
Example x=100, y=3. I could do this:
int x = 100;
for (int a = 1; a < x; a++) {
for (int b = a; b < x; b++) {
for (int c = b; c < x; c++) {
if (a+b+c == x) {
//DO SOMETHING
}
}
}
}
I think this would work (correct me if I'm wrong) but of course is not very efficient at all because I only want the cases where the if statement is true. And with larger y it takes ages. How could I do this efficiently?
From your algorithm, I can see that you want x=a+b+c with a<=b<=c.
Obviously for y = 3, we have 1<=a<=x/3, then a<=b<=(x-a)/2, c=x-b-a
For an given y, we get: 1<=a1<=x/y, a1<=a2<=(x-a1)/(y-1), ... ai<=a(i+1)<=(x-a1-...-ai)/(y-i)
But in you want a solution for an arbitrary y, you need a recursive algorithm.
Here is a java implementation:
public void split(int number, int pieces) {
total = 0;
dosplit(number, pieces, new ArrayList<Integer>());
}
private void dosplit(int number, int pieces, List<Integer> begin) {
if (pieces == 1) {
if (begin.isEmpty() || (number >= begin.get(begin.size() - 1))) {
begin.add(number);
total += 1;
//DO SOMETHING WITH BEGIN
begin.remove(begin.size() - 1);
}
}
else {
int start, end;
start = (begin.isEmpty()) ? 1 : begin.get(begin.size() - 1);
end = 1 + (1 + number - start)/pieces;
for(int i=start; i<=end; i++) {
begin.add(i);
dosplit(number - i, pieces - 1, begin);
begin.remove(begin.size() - 1);
}
}
split(10,3) correctly yields :
[1, 1, 8]
[1, 2, 7]
[1, 3, 6]
[1, 4, 5]
[2, 2, 6]
[2, 3, 5]
[2, 4, 4]
[3, 3, 4]
with as little useless steps as possible.
But split(504, 18) would yield an unmanageable number or solutions :-(

Divide and Conquer algorithm in java

I have to write an algorithm in Java that uses the
divide and conquer technique. Given an array V with n int elements
the algorithm should calculate the number of times that two consecutive
0's appear.
Example :If V = [3, 0, 0, 1, 0, 1, 3, 2, 0, 0, 0, 1, 2], the algorithm should return 3,
Note that 0, 0, 0 corresponds to having 2 pairs of consecutive zeros.
I have written the program as below but when I run it it gives me an ArrayIndexOutOfBoundsException.
What am I doing wrong ?
public class Test {
public static void main(String[] args){
int[] v = {3, 0, 0, 1, 0, 1, 3, 2, 0, 0, 0, 1, 2};
System.out.println(Conta_Zeri_Main(v));
}
public static int Conta_Zeri_Main(int[] v){
if (v.length == 0 || v.length == 1)
return 0;
else
return Conta_Zeri(v, 1, v.length);
}
public static int Conta_Zeri(int[] v, int i, int f){
int m,result,sx,dx;
if (i >= f)
return 0;
else{
m = (i + f)/2;
sx = Conta_Zeri(v, i, m);
dx = Conta_Zeri(v, m+1, f);
result = sx + dx;
if ((v[m] == v[m+1]) && (v[m] == 0))
result++;
return result;
}
}
}
Apart from the anomalies already pointed out,
In your code you do not check if v[m] = v[m+1] = 0. This will miss out some possibilities when the array is partitioned between 2 consecutive zeroes.
Change your if statement to:
if ( (m < v.length - 1 ) && (v[m] == v[m+1]) && (v[m] == 0) )

What is wrong with my checksum algorithm?

I am doing some practice problems for a competition and I have been working on this algorithm like all day. If you want to read the whole problem here it is, but I will give you a short explanation because it is kind of a long problem.
Problem:
You have to verify ID numbers by plugging the ID number into a checksum. The ID needs to be converted to base-10 before you can plug it into the algorithm. The ID number starts out as letters:
Z = 0, Y = 1, X = 2, W = 3, V = 4
I am not having trouble with the conversion from these letters to base-10, my conversion code is good so I'll show you the next part of the problem:
Part 2:
Once you have your base-10 ID number you need to plug it into the following algorithm:
Note: each ID number MUST be 8 digits long, 0's will precede a number that is not at least 8 digits.
checksum = F(0, d0) X F(1, d1) X F(2, d2) ...
So to simplify:
checksum = F(n, dn) X F(n+1, dn) ...
where n is the index of the digit
What is most important here, is that X is not the operation * (multiply). X is it's own operation defined later.
Note: The most significant digit seems to be d7 but I'm not sure, the problem is not very clear about it.
Here are the definitions for f(n1, n2), g(n) and the operator X:
f(n1, n2) =
g(n) =
operator X:
I assumed mod is the same thing as % in my code, I was not sure if there was another mod operation I am not familiar with.
My Structure
This is how I decided I wanted to solve the problem:
Convert the base-10 number into int[8]
Put each digit of the int[8] through f(n, dn)
Use the X operator to then combine them all together.
My Code
Here are my algorithm functions. I can comment them if they are confusing somewhere, but they really follow the algorithm listed above exactly.
/*
* This will return the checksum of the id.
* Formula: F(0, d0) X F(1, d1) ...
*
* F(n, dn) where n is the current index.
* X != * (multiply)!! X is a defined operator
*/
public static int getChecksum(int[] id)
{
int result = 0;
for(int x = 0;x < id.length;x++)
{
if(x == 0)
result = fOfxd(x, id[x]);
else{
result = opX(result, fOfxd(x, id[x]));
}
}
return result;
}
public static int gOfx(int x)
{
return GOFX[x];
}
public static int fOfxd(int x, int d)
{
switch(x)
{
case 0:
return d;
case 1:
return gOfx(d);
default:
return fOfxd(x - 1, gOfx(d));
}
}
public static int opX(int num1, int num2)
{
if(num1 < 5 && num2 < 5)
return (num1 + num2) % 5;
if(num1 < 5 && num2 >= 5)
return (num1 + (num2 - 5)) % 5 + 5;
if(num1 >= 5 && num2 < 5)
return ((num1 - 5) - num2) % 5 + 5;
return (num1 - num2) % 5;
}
public static final int[] GOFX = {1, 5, 7, 6, 2, 8, 3, 0, 9, 4};
Now, here is my main(String args[]) code:
Note: You can assume the functions parseBase10, and toArray are functioning properly. I have checked them with the input / output examples in the problem.
public static void main(String args[])
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
int ids = 0; // how many ids are we checking?
try
{
ids = Integer.parseInt(reader.readLine()); // get user input
String[] list = new String[ids]; // will hold all of the ids
for(int x = 0;x < list.length;x++)
list[x] = reader.readLine(); // reads all of the ids we will be checking
for(int x = 0;x < list.length;x++) // lets check the ids individually now
{
String stringID = list[x]; // the string representation of the id
int base10 = parseBase10(stringID);
int[] id = toArray(base10);
int checksum = getChecksum(id);
System.out.println(stringID);
System.out.println(base10);
System.out.println(Arrays.toString(id));
System.out.println(checksum);
}
}catch(Exception e){e.printStackTrace();}
break;
}
}
Want to compile it yourself?
Here is my full (unedited) code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main
{
public static void main(String args[])
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
int ids = 0; // how many ids are we checking?
try
{
ids = Integer.parseInt(reader.readLine()); // get user input
String[] list = new String[ids]; // will hold all of the ids
for(int x = 0;x < list.length;x++)
list[x] = reader.readLine(); // reads all of the ids we will be checking
for(int x = 0;x < list.length;x++) // lets check the ids individually now
{
String stringID = list[x]; // the string representation of the id
int base10 = parseBase10(stringID);
int[] id = toArray(base10);
int checksum = getChecksum(id);
System.out.println(stringID);
System.out.println(base10);
System.out.println(Arrays.toString(id));
System.out.println(checksum);
}
}catch(Exception e){e.printStackTrace();}
break;
}
}
/*
* This will return the checksum of the id.
* Formula: F(0, d0) X F(1, d1) ...
*
* F(n, dn) where n is the current index.
* X != * (multiply)!! X is a defined operator
*/
public static int getChecksum(int[] id)
{
int result = 0;
for(int x = 0;x < id.length;x++)
{
if(x == 0)
result = fOfxd(x, id[x]);
else{
result = opX(result, fOfxd(x, id[x]));
}
}
return result;
}
public static int gOfx(int x)
{
return GOFX[x];
}
public static int fOfxd(int x, int d)
{
switch(x)
{
case 0:
return d;
case 1:
return gOfx(d);
default:
return fOfxd(x - 1, gOfx(d));
}
}
public static int opX(int num1, int num2)
{
if(num1 < 5 && num2 < 5)
return (num1 + num2) % 5;
if(num1 < 5 && num2 >= 5)
return (num1 + (num2 - 5)) % 5 + 5;
if(num1 >= 5 && num2 < 5)
return ((num1 - 5) - num2) % 5 + 5;
return (num1 - num2) % 5;
}
/*
* This will convert a number to an array equivalent of that number
* The result will be 8 digites long with leading 0's if possible.
*
* EX:
* 12345 = {0, 0, 1, 2, 3, 4, 5, 6}
*/
public static int[] toArray(int value)
{
int result[] = new int[8];
for(int x = result.length - 1;x >= 0;x--)
{
result[x] = value % 10;
value /= 10;
}
return result;
}
/*
* converts a String sequence and converts it to a base 10 equivalent.
* Z = 0, Y = 1, X = 2, W = 3, V = 4
*
* EX:
* YY = 11(base-5) = 6(base-10)
*/
public static int parseBase10(String string) throws Exception
{
int multiplier = 1;
int result = 0; // in base 10
for(int x = string.length() - 1;x >= 0;x--)
{
char letter = string.charAt(x); // the letter we are parsing
int value = -1; // initial value, set to -1 to check for parsing error
for(int y = 0;y < VALUES.length;y++)
if(letter == VALUES[y])
value = y; // letter found in VALUES[]
if(value == -1)
throw new Exception("Could not parse: " + letter); // the specified letter was not found
result += (multiplier * value);
/* ^^ this moves the value to the correct digit place by using a multiplier:
* EX:
*
* current result: 45 (base-10)
* new value to parse: 2 (base-5)
* 45(base-10) + (2(base-5) * 25(base-10)) = 245 <-- correct output
*/
multiplier *= 5; // sets up multiplier for next value
}
return result;
}
public static final char[] VALUES = {'Z', 'Y', 'X', 'W', 'V'};
public static final int[] GOFX = {1, 5, 7, 6, 2, 8, 3, 0, 9, 4};
}
Here is the input I am giving my problem:
6
WYYXWVZXX
YWYWYYXWVZYY
YWYWYYXWVZYX
YYZWYYXWVZYX
YXXWYYXWVZXW
XYXWYYXWXYY
Here is what I get:
WYYXWVZXX
1274262
[0, 1, 2, 7, 4, 2, 6, 2]
2 *0*
YWYWYYXWVZYY
81352381
[8, 1, 3, 5, 2, 3, 8, 1]
0
YWYWYYXWVZYX
81352382
[8, 1, 3, 5, 2, 3, 8, 2]
4
YYZWYYXWVZYX
59868007
[5, 9, 8, 6, 8, 0, 0, 7]
0
YXXWYYXWVZXW
73539888
[7, 3, 5, 3, 9, 8, 8, 8]
5 *0*
XYXWYYXWXYY
22520431
[2, 2, 5, 2, 0, 4, 3, 1]
3 *0*
Where you see the *0*'s is where I am supposed to be getting 0, but I am getting a different value. Where is my checksum algorithm messing up?
Reading all of that feel free to ask for clarification on any part of my code.
BUG 1
The error is subtle. First of all, the digit description in the problem is: d7 d6 ... d1 d0
that means, d0 is the unit value of the decimal number.
Then, they say that F is left associative, and describe the process as :
F(0,d0) x F(1,d1) x F(2,d2) x ... x F(6,d6) x F(7,d7)
that means, you must first apply F to the operator to d0. BUT when you create the int array, the element at the 0 index is d7 , and since in this case the order matters, you get a wrong result.
To solve, you just have to reverse your int array rapresentation of the decimal value.
BUG 2
The second mistake is in the operation modulo 5. As you can read in the note of the problem, they say :
Note that -4 mod 5 = 1.
So copy-pasting hte operator x is a mistake. Change it with:
public static int opX(int num1, int num2)
{
if(num1 < 5 && num2 < 5)
return (num1 + num2) % 5;
if(num1 < 5 && num2 >= 5)
return (num1 + (num2 - 5)+5) % 5 + 5;
if(num1 >= 5 && num2 < 5)
return ((num1 - 5) - num2+20) % 5 + 5;
return (num1 - num2 +10) % 5;
}
and you'll get the expected result.
Here is the result with both bugs fixed :
1274262
[2, 6, 2, 4, 7, 2, 1, 0]
0
YWYWYYXWVZYY
81352381
[1, 8, 3, 2, 5, 3, 1, 8]
0
YWYWYYXWVZYX
81352382
[2, 8, 3, 2, 5, 3, 1, 8]
1
YYZWYYXWVZYX
59868007
[7, 0, 0, 8, 6, 8, 9, 5]
0
YXXWYYXWVZXW
73539888
[8, 8, 8, 9, 3, 5, 3, 7]
0
XYXWYYXWXYY
22520431
[1, 3, 4, 0, 2, 5, 2, 2]
0
EDIT
For a more general solution of the BUG 2, check Martijn Courteaux answer.
Your mod logic is broken. The website says:
Note that -4 % 5 = 1.
In Java, this is not true: (-4) % 5 == -4. So implement your own mod(int a, int b) method:
public static int mod(int a, int b)
{
while (a < 0) a += b;
while (a >= b) a -= b;
return a;
}
Or a more performant implementation as suggested by #durron597:
public static int mod(int a, int b)
{
a %= b;
return a < 0 ? a + b : a;
}
This is really important since you will have negative values here
(Eg: assume num1 = 5 and num2 = 4):
if(num1 >= 5 && num2 < 5)
return ((num1 - 5) - num2) % 5 + 5;

Categories