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;
Related
For example, {1, 4, 45, 6, 0, 19} and the number 51 should return 3, because the number of elements in the smallest subarray which together are greater than 51 are 3: {4,45,6}`.
{7, 2, 5, 10, 1} and the number 9 should return 1, because the number of the elements in the smallest subarray possible that is greater than 9 is {10}.
If array is null or empty, or the array has no subarray that is greater than the given number, the method has to return -1.
I'm not allowed to use array package from java.util.
My goal is to execute the method in O(n) time.
This is my code so far, if the array has no subarray greater than the given number, it returns an OutofBounds error.
Anyone has a clue?
public static int smallestSubSum(int arr[], int x) {
int left = 0, right = 1, smallest = 0;
int sum = arr[right];
for (int i = 1; i < arr.length; i++) {
if (sum > x)
smallest = left - right;
else
right++;
sum += arr[right];
if (sum > x && left - right < smallest) {
smallest = left - right;
left++;
} else
sum -= arr[left];
left++;
if (sum > x && left - right < smallest)
smallest = left - right;
}
return smallest;
}
Edit: Perhaps I should explain what I tried to do with my code, basically I wanted the sum to hold the first two elements in the code, and then compare with each 'if' iteration if the sum of the current elements are greater or less than X, if not I raise the right element to go further, if yes I erase the first element, the 'left' one.
The array of {1, 4, 45, 6, 0, 19} and the number 51 returns 2, even though the result should be 3. I don't know why, because my right reaches the index 3 which is 6 and the left one reaches index 1 which is 4, so the result should indeed be {4,45,6} but it doesn't get to it.
This is the best I could do.
Here are my test results.
[1, 4, 45, 6, 0, 19] -> 51
3
[7, 2, 5, 10, 1] -> 9
1
[1, 4, 45, 6, 0, 19] -> 200
-1
I just cycled through the array with a for loop. Whenever the total exceeded the X amount, I subtracted values until the total dropped below the X amount.
Here's the complete runnable code I tested with.
import java.util.Arrays;
public class SmallestSubarray {
public static void main(String[] args) {
int[] arr1 = new int[] { 1, 4, 45, 6, 0, 19 };
int x1 = 51;
System.out.println(Arrays.toString(arr1) + " -> " + x1);
System.out.println(smallestSubSum(arr1, x1));
int[] arr2 = new int[] { 7, 2, 5, 10, 1 };
int x2 = 9;
System.out.println(Arrays.toString(arr2) + " -> " + x2);
System.out.println(smallestSubSum(arr2, x2));
int[] arr3 = new int[] { 1, 4, 45, 6, 0, 19 };
int x3 = 200;
System.out.println(Arrays.toString(arr3) + " -> " + x3);
System.out.println(smallestSubSum(arr3, x3));
}
public static int smallestSubSum(int arr[], int x) {
if (arr == null || arr.length < 1) {
return -1;
}
int sum = 0;
int minCount = Integer.MAX_VALUE;
int index = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
while (sum > x) {
minCount = Math.min(i - index + 1, minCount);
sum -= arr[index];
index++;
}
}
return (minCount == Integer.MAX_VALUE) ? -1 : minCount;
}
}
This is leetCode problem. I solved it using the following method but its giving stack overflow error.
Given an array of integers nums and an integer target.
Return the number of non-empty subsequences of nums such that the sum of the minimum and maximum element on it is less or equal than the target.
Since the answer may be too large, return it modulo 10^9 + 7.
Input: nums = [3,5,6,7], target = 9
Output: 4
Explanation: There are 4 subsequences that satisfy the condition.
[3] : Min value + max value <= target (3 + 3 <= 9)
[3,5] : (3 + 5 <= 9)
[3,5,6] : (3 + 6 <= 9)
[3,6] : (3 + 6 <= 9)
enter code here:
import java.lang.Math;
class Solution {
static int maxIndex=0;
static long M=1000000007;
public int numSubseq(int[] nums, int target) {
Arrays.sort(nums);
maxIndex=nums.length-1;
return numSubseq(nums,target,0);
}
public int numSubseq(int[] nums,int target, int i){
if(target==0 || nums.length==0 || i==nums.length)
return 0;
int res=0;
if(2*nums[i]<=target){
res=1;
if(nums[i]<nums[maxIndex]){
int j=maxIndex;
while(j>i){
if(nums[i]+nums[maxIndex]<=target)
break;
j--;
}
maxIndex=j;
if(nums[i]+nums[maxIndex]<=target && i!=maxIndex)
{
int diffIndex=maxIndex-i;
res+=Math.pow(2,diffIndex)-1;
}
}
}
else{
return 0;
}
return (int)((res+numSubseq(nums,target,i++))%M);
}
}``
I guess there would be a problem here in this line:
return (int)((res+numSubseq(nums,target,i++))%M);
We can solve the problem a bit easier though, similarly using sort, then two pointers.
Test with a b.java:
import java.util.*;
class Solution {
private static final int MOD = (int)1e9 + 7;
public static final int numSubseq(
final int[] nums,
final int target
) {
Arrays.sort(nums);
int[] pows = new int[nums.length];
pows[0] = 1;
int subsequences = 0;
int left = 0;
int right = nums.length - 1;
for (int index = 1 ; index < nums.length ; ++index) {
pows[index] = pows[index - 1] * 2;
pows[index] %= MOD;
}
while (left <= right) {
if (nums[left] + nums[right] > target) {
--right;
} else {
subsequences += pows[right - left++];
subsequences %= MOD;
}
}
return subsequences;
}
}
class b {
public static void main(String[] args) {
System.out.println(new Solution().numSubseq(new int[] {3, 5, 6, 7}, 9));
System.out.println(new Solution().numSubseq(new int[] {3, 3, 6, 8}, 10));
System.out.println(new Solution().numSubseq(new int[] {2, 3, 3, 4, 6, 7}, 12));
System.out.println(new Solution().numSubseq(new int[] {5, 2, 4, 1, 7, 6, 8}, 16));
}
}
prints
4
6
61
127
public class Solution {
public ArrayList<Integer> plusOne(ArrayList<Integer> A) {
int n = A.size();
// Add 1 to last digit and find carry
A.set(n - 1, A.get(n - 1) + 1);
int carry = A.get(n - 1) / 10;
A.set(n - 1, A.get(n - 1) % 10);
// Traverse from second last digit
for (int i = n - 2; i >= 0; i--) {
if (carry == 1) {
A.set(i, A.get(i) + 1);
carry = A.get(i) / 10;
A.set(i, A.get(i) % 10);
}
}
// If carry is 1, we need to add
// a 1 at the beginning of vector
if (carry == 1)
A.add(0, 1);
return A;
}
}
Question is:
Given a non-negative number represented as an array of digits,
add 1 to the number ( increment the number represented by the digits ).
The digits are stored such that the most significant digit is at the head of the list.
Example:
If the vector has [1, 2, 3]
the returned vector should be [1, 2, 4]
as 123 + 1 = 124.
Wrong Answer. Your program's output doesn't match the expected output. You can try testing your code with custom input and try putting debug statements in your code.
Your submission failed for the following input:
A : [ 0, 0, 4, 4, 6, 0, 9, 6, 5, 1 ]
Your function returned the following :
0 4 4 6 0 9 6 5 2
The expected returned value :
4 4 6 0 9 6 5 2
Use below method
private ArrayList<Integer> recursiveCheckZero() {
if (arrayList.get(0) == 0) {
arrayList.remove(0);
recursiveCheckZero();
} else {
return arrayList;
}
}
This method will be used to zero at first position, it would be called recursively until all zeros get removed. and when there will be no zero at first position it will return final ArrayList of integers as actual result
int sum=0;
int carry=0;
int i=0;
while (i < A.size() - 1 && A.get(i) == 0) {
A.remove(i); //remove all zeroes in front
}
for(i=A.size()-1;i>=0;i--)
{
int n=A.get(i);
sum=n+carry;
if(i==A.size()-1)
{
sum = sum+1;
}
carry=sum/10;
sum=sum%10;
A.set(i,sum);
}
if (carry !=0)
A.add(0,1);
return A;
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 :-(
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");}
}
}