Algorithm to calculate values based on linear equations - java

I am working to calculate values of various Paycodes in a PayStructure based on linear equations using java. My different equations are as below:
CTC = Fixed Value
Basic = CTC * 0.4
HRA = Basic/2
ConveyanceAllowance = Fixed Value
ProvidentFund = Basic * 0.12
Gratuity = Basic * .0481
OtherAllowance = (CTC - (Basic + HRA + ConveyanceAllowance + ProvidentFund + Gratuity))
I have tried using the solution given here. But this solution will only work in case all the calculated values are integers and in my case, the values could contain decimal figures as well. My modified code as per the above conditions is as below:
public class PayStructure {
public static void main(String[] args) {
findAndprintSolutions(1, 1000000);
}
private static void findAndprintSolutions(int from, int to) {
for (int a = from; a < to; a++) {
for (int b = from; b < to; b++) {
for (int c = from; c < to; c++) {
for (int d = from; d < to; d++) {
for (int e = from; e < to; e++) {
for (int f = from; f < to; f++) {
for (int g = from; g < to; g++) {
if (isSolution(a, b, c, d, e, f, g))
printSolution(new int[] { a, b, c, d, e, f, g });
}
}
}
}
}
}
}
}
private static boolean isSolution(int a, int b, int c, int d, int e, int f, int g) {
if (a != 100000)
return false;
if (b != a * (.4))
return false;
if (c != b / 2)
return false;
if (d != 10000)
return false;
if (e != b * (.12))
return false;
if (f != b * (.0481))
return false;
if (g != (a - (b + c + d + e + f)))
return false;
return true;
}
private static void printSolution(int[] variables) {
StringBuilder output = new StringBuilder();
for (int variable : variables) {
output.append(variable + ", ");
}
output.deleteCharAt(output.length() - 1);
output.deleteCharAt(output.length() - 1);
System.out.println(output.toString());
}
}
Moreover the above mentioned code will be terminated as the maximum value of CTC could be millions and depending on the number of variables, time complexity will end up to be millions^NumberOfVariables. Is there any other possibility to calculate the values based on the given equations? The number of equations and variables could vary but there will be a solution to calculate value of each variable, so any inputs for a generic solution would be better.
E.g.: If CTC = 100000 and ConveyanceAllowance = 10000, the code should return the output as:
Basic = 40000
HRA = 20000
ProvidentFund = 4800
Gratuity = 1924
OtherAllowance = 23276

Maybe your best bet would be to figure out how to get this into the form of a system of linear equations of the form c[1]x[1] + c[2]x[2] … + c[n]x[n] = 0. From there, you can solve the system using widely established techniques for linear systems. See the Wikipedia page for lots of information. You could either have the users provide input to your method in this form, or you could do a small amount of processing on each equation to transform it (e.g., if all the equations have one variable on the LHS as in your example, flip the sign and put it on the end of the RHS).
Explaining the theory of solving a system of linear equations is beyond the scope of this answer but, basically, your system will either be uniquely determined if there is one valid assignment, overdetermined if no valid assignment exists, or underdetermined if infinitely many assignments are possible. If there is a unique assignment you will get numbers; if the system is underdetermined you'll at least get a set of constraints that must hold of any of the infinitely many solutions; if underdetermined, you'll get nothing and know why.

Use the some linear algebra library for Java. Solve the system of linear equations using matrix operations as documented here, for instance. Your deeply nested loop is too slow, there are much better algorithms available.

This is how I solved this. Firstly I created equations by taking all the variables to the left side and values & 0 to the right side:
CTC = 1000000
(0.4)CTC - Basic = 0
(0.5)Basic-HRA = 0
ConvAll = 10000
(0.12)Basic-PF = 0
(0.0481)Basic - Gratuity = 0
CTC - (Basic + HRA + ConvAll + PF+ Gratuity + OtherAll) = 0
Then I created a matrix like this:
|1 0 0 0 0 0 0| |CTC | = |1000000|
|0.4 -1 0 0 0 0 0| |Basic | = |0 |
|0 0.5 -1 0 0 0 0| |HRA | = |0
|0 0 0 1 0 0 0| |ConvAll | = |10000 |
|0 0.12 0 0 -1 0 0| |PF | = |0 |
|0 0.0481 0 0 0 -1 0| |Gratuity| = |10000 |
|1 -1 -1 -1 -1 -1 -1| |OtherAll| = |0 |
After this, I calculated the product of (inverse of above 1st matrix) and (right most matrix) and got the corresponding values of each component using the below code:
public class Matrix
{
static int n = 0;
public static void main(String argv[]) {
Scanner input = new Scanner(System.in);
System.out.println("Enter the dimension of square matrix: ");
n = input.nextInt();
double a[][] = new double[n][n];
System.out.println("Enter the elements of matrix: ");
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
a[i][j] = input.nextDouble();
double d[][] = invert(a);
System.out.println();
System.out.println("Enter the equation values: ");
System.out.println();
double b[][] = new double[n][1];
for (int i = 0; i < n; i++) {
b[i][0] = input.nextDouble();
}
double e[][] = multiplyMatrix(d, b);
System.out.println();
System.out.println("The final solution is: ");
System.out.println();
for (int i = 0; i < n; i++) {
for (int j = 0; j < 1; j++) {
System.out.printf(e[i][j] + " ");
}
System.out.println();
}
input.close();
}
public static double[][] invert(double a[][]) {
int n = a.length;
double x[][] = new double[n][n];
double b[][] = new double[n][n];
int index[] = new int[n];
for (int i = 0; i < n; ++i)
b[i][i] = 1;
// Transform the matrix into an upper triangle
gaussian(a, index);
// Update the matrix b[i][j] with the ratios stored
for (int i = 0; i < n - 1; ++i)
for (int j = i + 1; j < n; ++j)
for (int k = 0; k < n; ++k)
b[index[j]][k] -= a[index[j]][i] * b[index[i]][k];
// Perform backward substitutions
for (int i = 0; i < n; ++i) {
x[n - 1][i] = b[index[n - 1]][i] / a[index[n - 1]][n - 1];
for (int j = n - 2; j >= 0; --j) {
x[j][i] = b[index[j]][i];
for (int k = j + 1; k < n; ++k) {
x[j][i] -= a[index[j]][k] * x[k][i];
}
x[j][i] /= a[index[j]][j];
}
}
return x;
}
// Method to carry out the partial-pivoting Gaussian
// elimination. Here index[] stores pivoting order.
public static void gaussian(double a[][], int index[]) {
int n = index.length;
double c[] = new double[n];
// Initialize the index
for (int i = 0; i < n; ++i)
index[i] = i;
// Find the rescaling factors, one from each row
for (int i = 0; i < n; ++i) {
double c1 = 0;
for (int j = 0; j < n; ++j) {
double c0 = Math.abs(a[i][j]);
if (c0 > c1)
c1 = c0;
}
c[i] = c1;
}
// Search the pivoting element from each column
int k = 0;
for (int j = 0; j < n - 1; ++j) {
double pi1 = 0;
for (int i = j; i < n; ++i) {
double pi0 = Math.abs(a[index[i]][j]);
pi0 /= c[index[i]];
if (pi0 > pi1) {
pi1 = pi0;
k = i;
}
}
// Interchange rows according to the pivoting order
int itmp = index[j];
index[j] = index[k];
index[k] = itmp;
for (int i = j + 1; i < n; ++i) {
double pj = a[index[i]][j] / a[index[j]][j];
// Record pivoting ratios below the diagonal
a[index[i]][j] = pj;
// Modify other elements accordingly
for (int l = j + 1; l < n; ++l)
a[index[i]][l] -= pj * a[index[j]][l];
}
}
}
public static double[][] multiplyMatrix(double a[][], double b[][]) {
double c[][] = new double[n][1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < 1; j++) {
for (int k = 0; k < n; k++) {
c[i][j] = c[i][j] + a[i][k] * b[k][j];
}
}
}
return c;
}
}
Thank you all for the leads.

Related

How do I calculate the number of Lines produced for the largest test-case when k = 12?

Problem: Given 6 < k < 13 integers, enumerate all possible subsets of size 6 of these integers in a sorted order. Since the size of the required subset is always 6 and the output has to be sorted lexicographically (the input is already sorted), the easiest solution is to use 6 nested loops as shown below.
I read that this code is efficient because it'll only produces 924 lines of output for the largest test-case when k = 12; however, I don't seem to get how the 924 lines were counted.
(Code solved using Iterative Complete Search problem solving paradigm)
public class loops {
public static void main(String[] args) {
int k = 12;
int[] S = {1,2,3,4,5,6,7,8,9,10,11,12};
for (int i = 0; i < k; i++) {
for (int a = 0; a < k - 5; a++) {
for (int b = a + 1; b < k - 4; b++) {
for (int c = b + 1; c < k - 3; c++) {
for (int d = c + 1; d < k - 2; d++) {
for (int e = d + 1; e < k - 1; e++) {
for (int f = e + 1; f < k; f++) {
System.out.println( S[a] + ""+ S[b] + S[c] + S[d] + S[e] + S[f]);
}
}
}
}
}
}
}
}
}
You're answering the combinatorial question how much "12 choose 6" is. By definition, the following holds:
12 choose 6 = 12!/6!(12-6)!
= 12!/(6!6!)
= 12*11*10...*2*1/(6*5*4*3*2*1*6*5*4*3*2*1)
= 479001600/(720*720)
= 924

Array length trouble in Java?

so I am in the middle of working on a problem requiring me to:
Use 3 nested loops to generate every combination of (F^5-E^5-D^5) store all these combinations. Then use 3 different nested loops to generate every combination of (A^5+B^5+C^5) and store all these values. Where 0 < A ≤ B ≤ C ≤ D ≤ E ≤ F ≤ N
I have been following this thread which is exactly what I am trying to accomplish.
The problem I am having is the way my code is set up, the array that I am storing the values in will be overwritten every time the loop goes around again.
How long does the array need to be to store the values (N^3 maybe)? And how can I do it without overwriting?
Here is my code so far:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter the value for N:");
int n = scan.nextInt();
int countF = n;
double[] fifth_orderN = new double[n+1];
double[] F_answer = new double[n+1];
double[] A_answer = new double[n+1];
for(int i = 1; i != n+1; i++)
{
fifth_orderN[i] = Math.pow(i, 5);
}
for(int i = 1; i != n+1 ; i++)
{
double F = Math.pow(countF, 5);
countF--;
for(int j = 1; j != n+1 ; j++)
{
double E = fifth_orderN[j];
for(int k = 1; k != n+1; k++)
{
double D = fifth_orderN[k];
double ans = (F-(D+E));
if(ans < 0)
{
break;
}
else
{
F_answer[k] = ans;
}
}
}
}
for(int i = 1; i != n+1; i++)
{
double A = fifth_orderN[i];
for(int j = 1; j != n+1; j++)
{
double B = fifth_orderN[j];
for(int k = 1; k != n+1; k++)
{
double C = fifth_orderN[k];
double ans = (A + B + C);
A_answer[k] = ans;
}
}
}
}

Tape-Equilibrium Codility Training program

I submitted a solution to Tape Equilibrium problem in Codility. [Codility training][1]
The problem is described as follows:
A non-empty zero-indexed array A consisting of N integers is given. Array A represents numbers on a tape.
Any integer P, such that 0 < P < N, splits this tape into two non-empty parts: A[0], A[1], ..., A[P − 1] and A[P], A[P + 1], ..., A[N − 1].
The difference between the two parts is the value of: |(A[0] + A[1] + ... + A[P − 1]) − (A[P] + A[P + 1] + ... + A[N − 1])|
In other words, it is the absolute difference between the sum of the first part and the sum of the second part.
The solution I submitted is:
class Solution {
public int solution(int[] A) {
long d = A[0] - A[A.length-1];
int l = 1;
int r = A.length -2;
while(l <= r) {
if (Math.abs(d + A[l]) < Math.abs(d - A[r])) {
d += A[l];
l++;
}
else {
d -= A[r];
r--;
}
}
return (int) Math.abs(d);
}
}
I achieved 85% accuracy but couldn't get to correct for some use case. Can someone help me to find what's wrong with this solution. Thanks
The following is my 100% solution:
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
// int idx = 0;
int sumPre = A[0];
int sumPost = 0;
for (int i = 1; i < A.length; i++) {
sumPost += A[i];
}
int difMin = Math.abs(sumPost - sumPre);
int tempSub = 0;
for (int i = 1; i < A.length - 1; i++) {
sumPre += A[i];
sumPost -= A[i];
tempSub = Math.abs(sumPost - sumPre);
if (tempSub < difMin) {
difMin = tempSub;
// idx = i+1;
}
}
return difMin;
}
}
I can not find their test input, but I find a weird thing is that when "for(int i = 1; i < A.length - 1; i++) " is changed to " for(int i = 1; i < A.length; i++)", then it will trigger two wrong runs...So it still must be a border value issue.
If any one find a test input can break the validity, please share with us, thanks.
Caution: {1,-1} indeed triggered the problem, since P < N, so at least one element should be left in the right part. -> {1,-1},{} is not a valid solution according to the problem definition.
Problem solved.
C# and Linq version for 100% as of May 2021:
public int solution(int[] A)
{
int left = A[0];
int right = A.Skip(1).Aggregate((c,x)=> c+=x);
int min = Math.Abs(left-right);
for(int i=1; i < A.Length-1; i++)
{
left+=A[i];
right-=A[i];
min = Math.Min(min,Math.Abs(left-right));
}
return min;
}
I also tried and got only 83%. My solution:
class Solution {
public int solution(int[] A) {
int[] leftSums = new int[A.length];
for (int i = 0; i < leftSums.length; i++) {
leftSums[i] = 0;
}
int sum = 0;
for (int i = 0; i < A.length; i++) {
sum += A[i];
leftSums[i] = sum;
}
/*
for (int i = 0; i < leftSums.length; i++) {
if (i == 0) {
System.out.print("Left Sums Array is : [");
}
if (i == leftSums.length - 1) {
System.out.println(leftSums[i] + "]");
}
System.out.print(leftSums[i] + ", ");
}
*/
final int total = sum;
//System.out.println("Total is " + total);
int minDiff = Integer.MAX_VALUE;
int currDiff = 0;
for (int i = 0; i < leftSums.length; i++) {
currDiff = Math.abs(leftSums[i] - (total - leftSums[i]));
if (currDiff < minDiff) {
minDiff = currDiff;
}
}
return minDiff;
}
}
Below are those which failed for correctness.
double
two elements 1.280 s WRONG ANSWER
got 0 expected 2000
small
small elements 1.304 s WRONG ANSWER
got 0 expected 20
I tested myself for 2 elements and it worked for me.
I share my 100% score Java solution:
class Solution {
public int solution(int[] A) {
final int size = A.length;
long sumMin = (int)A[0];
long sumMax = 0;
for (int i = 1; i < size; i++) {
sumMax += (int)A[i];
}
int minDif = (int)Math.abs(sumMax - sumMin);
for (int i = 1; i < size; i++) {
int dif = (int)Math.abs(sumMax - sumMin);
if (dif < minDif) {
minDif = dif;
}
sumMin += A[i];
sumMax -= A[i];
}
return minDif;
}
}
The trick is that looping the array twice your complexity is 2N, which is O(N).
Addition results should be 'long' in order not to have problems with big extremes.
For %83 results, the problem is it says "splits this tape into two non-empty parts". So if you split for A[0], your first array will be empty. So you should start with A[1].
Ruby 100%
def solution(a)
left = a.inject(:+)
right = 0
a[0...-1].inject(Float::INFINITY) do |min, el|
left -=el
right += el
candidate = (right-left).abs
min < candidate ? min : candidate
end
end
You can actually do that, with one loop in C#.
Add Linq:
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
long sum = A.Sum(p => (long)p);
int val1 = Convert.ToInt32(A.GetValue(0));
int val2 = Convert.ToInt32(sum - val1);
int result = Math.Abs(val1 - val2);
for (int i = 1; i < A.Length-1; i++)
{
val1 += Convert.ToInt32(A.GetValue(i));
val2 -= Convert.ToInt32(A.GetValue(i));
if (result > Math.Abs(val1 - val2))
{
result = Math.Abs(val1 - val2);
}
}
return result;
}
Counterexample for user699681: A = {0, 1, 2, -5, 2},
and for Ism: A = {1, -1}.
TapeEquilibrium in C
int solution(int A[], int N) {
// write your code in C90
long int s_r=0,s_l=A[0],sum=A[0];
int i,min=11111111,r;
for(i=1;i<N;i++)
sum+=A[i];
for(i=1;i<N;i++)
{
s_r=sum-s_l;
r=(int)(s_l-s_r);
if(r<0) r=-r;
if(min>r)min=r;
if(min==0)break;
s_l=sum-s_r+A[i];
}
return min;
}
.. Or even a bit shorter to get 100%
public int solution(int[] A) {
int sumMin = A[0];
int sumMax = 0;
for (int i = 1; i < A.length; i++) {
sumMax += A[i];
}
int minDif = Math.abs(sumMin - sumMax);
for (int i = 1; i < A.length - 1; i++) {
sumMin += A[i];
sumMax -= A[i];
minDif = Math.min(minDif, Math.abs(sumMin - sumMax));
}
return minDif;
}
Here's my implementation using Java 8 IntStream to simplify the sum process...
100% Correct, 100% Performance.
import java.util.stream.IntStream;
public class TapeEquilibrium {
public static int diffIndex( int[] A ) {
long lower = 0, diff = 0, higher = IntStream.of( A ).asLongStream().sum(), minDiff = Integer.MAX_VALUE;
for(int i = 0; i < A.length-1; i++) {
lower += A[i];
higher -= A[i];
diff = Math.abs( higher - lower);
if( diff < minDiff ) {
minDiff = diff;
}
}
return (int) minDiff;
}
public static void main( String[] args ) {
int[] A = { 3, 1, 2, 4, 3 };
System.out.println( diffIndex( A ) );
}
}
here is my Solution with 100% correctness & performance
int solution(int A[], int N)
{
int sum,i;
sum=0;
for(i=0;i<N;i++)
{
sum+=A[i];
A[i]=sum;
}
int min_diff=abs(sum-A[0]*2);
for(i=0;i<N-1;i++)
{
int tmp;
tmp=abs(sum-A[i]*2);
if(tmp<min_diff)
min_diff=tmp;
}
return min_diff;
}
Try this one:
Class Solution {
public int solution(int[] A) {
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
int len = A.length;
int min = 1 ;
for(int i=0; i<len; i++){
sum2 += A[i];
}
for(int i=0; i< len-1 ; i++){
sum1 += A[i];
sum3 = sum2-sum1;
if( min > Math.abs(sum1- sum3)){
min = Math.abs( sum1 - sum3);
}
}
return min;
}
}
Here is 100% in scala.
def solution(A: Array[Int]): Int = {
//get the whole sum
val allSum = A.sum
//calculate left and right sum
var sumLeft = A(0)
var sumRight = allSum - sumLeft
//set initial diff for P=1
var minDiff = math.abs(sumLeft-sumRight) //difference
// loop for all P after the initial P position
for(p <- 1 to A.length-2){
//recalculate values
sumLeft += A(p)
sumRight -= A(p)
if(math.abs(sumLeft-sumRight) < minDiff){
// if difference is smaller then save new min diff
minDiff = math.abs(sumLeft-sumRight)
}
}
minDiff
}
Performance: https://codility.com/demo/results/trainingZNZCZN-AGC/
long sumofall = 0, leftsideSum = A[0], rightsidesum=0;
int x,LR = 0;
ArrayList listResult = new ArrayList();
for(x=0;x<A.Length;x++)
{
sumofall+= A[x];
}
for(x=1;x<A.Length;x++)
{
rightsidesum = sumofall-leftsideSum;
LR = (int)(rightsidesum - leftsideSum);
if(LR < 0)
{
LR=-LR;
}
listResult.Add(LR);
leftsideSum+=A[x];
}
listResult.Sort();
return Convert.ToInt32(listResult[0].ToString());
}
I share my 100% solution using Java 8.
public class TapeEquilibrium {
public int tapeEquilibrium(int[] A) {
final int N = A.length;
long minimalSum = (int) A[0];
int[] rightSide = Arrays.copyOfRange(A, 1, N);
long maximalSum = IntStream.of(rightSide).sum();
int minimalDifference = (int) Math.abs(maximalSum - minimalSum);
for (int i = 1; i < N; i++) {
int difference = (int) Math.abs(maximalSum - minimalSum);
minimalDifference = difference < minimalDifference ? difference : minimalDifference;
minimalSum += A[i];
maximalSum -= A[i];
}
return minimalDifference;
}
}
Here is my C# solution. Score 100%
if (A == null || A.Length == 0)
{
return 0;
}
int d1 = 0;
int d2 = A.Sum();
int p = 1;
int x = int.MaxValue;
// Replaced using A.sum();
//for (int i=0; i < A.Length; i++)
//{
// d2 += A[i];
//}
for (int j = 0; j < A.Length; j++)
{
if (j < p)
{
d1 += A[j];
}
int ad = Math.Abs(d1 - (d2 - d1));
x = Math.Min(x, ad);
if (p == A.Length -1) { break; }
p++;
}
return x;
Below is my solution which got 100% . As most of you guys did I first got the sum of the array then go through it while adding up left and right parts and then getting the absolutes of them and putting the results into a map then checking the map for the minimum value .
int totalLeft = 0;
int totalRight = 0;
int total = 0;
int result = 0;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < A.length; i++) {
total += A[i];
}
for (int i = 0; i < A.length - 1; i++) {
totalRight = total - (A[i] + totalLeft);
totalLeft += A[i];
result = Math.abs(totalLeft - totalRight);
map.put(i, result);
}
return Collections.min(map.values());
TapeEquilibrium in Swift 4
public func solution(_ A : inout [Int]) -> Int {
let P = 1
var splitIndex = P
var firstPartSum = A[splitIndex - 1]
var secondPartSum = Array(A[splitIndex..<A.count]).reduce(0, +)
var minimalDifference = abs(firstPartSum - secondPartSum)
if minimalDifference == 0 {
return minimalDifference
}
splitIndex += 1
while splitIndex < A.count {
firstPartSum += A[splitIndex - 1]
secondPartSum -= A[splitIndex - 1]
let dif = abs(firstPartSum - secondPartSum)
if dif == 0 {
return dif
}
if dif < minimalDifference {
minimalDifference = dif
}
splitIndex += 1
}
return minimalDifference
}
No one posted Javascript solution yet so here is mine with comments:
// you can write to stdout for debugging purposes, e.g.
// console.log('this is a debug message');
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
// Making it shorter.
let len = A.length;
// Definitely need to store, and initialise first value.
let left = new Array(len);
left[0] = A[0];
// Same as above, but initialise for last value.
let right = new Array(len);
right[len - 1] = A[len - 1];
let trackLowest = Number.MAX_SAFE_INTEGER;
// One shot calculate for both at any element (from 'outwards' 'in').
// Note there is 2 elements at least, and we already preset the first
// element, so we start and build from index 1.
for (let i = 1; i < len; ++i) {
left[i] = left[i - 1] + A[i];
right[len - 1 - i] = right[len - i] + A[len - 1 - i];
}
// Once the above is done, it's time to calculate the difference.
// If I am at index 0, then I want sum of index 0 AND left, and sum of index
// 1 and right (note not index 0 also).
// We stop before len - 1 because that's the rules and the sum of right will
// have been out of bounds if we want difference for last index, isn't it?
for (let i = 0; i < len - 1; ++i) {
let smallestDiff = Math.abs(left[i] - right[i + 1]);
if (smallestDiff < trackLowest) {
trackLowest = smallestDiff;
}
}
return trackLowest;
}
Basically sum up as you walk the loop simultaneously for the left and right side.
Once done, just get the difference, that's it. O(n) complexity.
My 100% JavaScript solution with O(N) time complexity (should be pretty self-explanatory):
function solution(A) {
let left = 0;
let right = A.reduce((sum, cur) => sum + cur, 0);
let min = Infinity;
for (let p = 0, len = A.length - 1; p < len; p++) {
left += A[p];
right -= A[p];
min = Math.min(min, Math.abs(left - right));
}
return min;
}
100% in Swift 4 for correctness & performance
Detected Time Complexity: 0(n)
var sumMin = A[0]
var sumMax = 0
for i in 1..<A.count {
sumMax += A[i]
}
var diff = abs(sumMin - sumMax)
for i in 1..<A.count-1 {
sumMin += A[i]
sumMax -= A[i]
diff = min(diff, abs(sumMin - sumMax));
}
return diff
Here mine in Java,
// got 91% because "int totalRight = (Arrays.stream(A).sum() - A[0]);" take too long to load
int totalLeft = A[0];
int totalRight = (Arrays.stream(A).sum() - A[0]);
//int afterMinus = 0;
int min = 0;
min = Math.abs(totalLeft - totalRight);
for(int i=1; i<(A.length-1); i++) {
//for(int j=A.length; j>0; j--) {
totalLeft += A[i];
totalRight -= A[i];
//System.out.println("totalLeft = "+ totalLeft);
//System.out.println("totalRight = "+ totalRight);
if(Math.abs(totalLeft - totalRight) < min) {
//System.out.println("min = "+ min);
min = Math.abs(totalLeft - totalRight);
}
}
return min;
// got 100% because change "int totalRight = (Arrays.stream(A).sum() - A[0]);" into for loop
//int totalSum = Arrays.stream(A).sum();
int totalLeft = A[0];
int totalRight = 0;
//int afterMinus = 0;
int min = 0;
for(int i=1; i<A.length; i++) {
totalRight += A[i];
}
min = Math.abs(totalLeft - totalRight);
for(int i=1; i<(A.length-1); i++) {
//for(int j=A.length; j>0; j--) {
totalLeft += A[i];
totalRight -= A[i];
//System.out.println("totalLeft = "+ totalLeft);
//System.out.println("totalRight = "+ totalRight);
if(Math.abs(totalLeft - totalRight) < min) {
//System.out.println("min = "+ min);
min = Math.abs(totalLeft - totalRight);
}
}
return min;
Well, from 91% to 100%, thanks to #sebadagostino after surfing for almost 2 hours for the logic and hints.

Compute Prefix Function in String Matching

What am i doing wrong here?
Java code for computing prefix function. Two input are right but the last one is wrong.
Here's the pseudocode:
Java code:
class Main {
// compute prefix function
public static void main(String[] args) {
String p = "422213422153342";
String x = "ababbabbabbababbabb";
String y = "ababaca";
printOutput(p);
printOutput(y);
System.out.println();System.out.println();
System.out.println("the prefix func below is wrong. I am not sure why.");
System.out.print("answer should be: 0 0 1 2 0 1 2 0 1 2 0 1 2 3 4 5 6 7 8");
printOutput(x);
}
static void printOutput(String P){
System.out.println();System.out.println();
System.out.print("p[i]: ");
for(int i = 0; i < P.length(); i++)System.out.print(P.charAt(i) + " ");
System.out.println();
System.out.print("Pi[i]: ");
compute_prefix_func(P);
}
public static void compute_prefix_func(String P){
int m = P.length();
int pi[] = new int[m];
for(int i = 0; i < pi.length; i++){
pi[i] = 0;
}
pi[0] = 0;
int k = 0;
for(int q = 2; q < m; q++){
while(k > 0 && ( ((P.charAt(k) + "").equals(P.charAt(q) + "")) == false)){
k = pi[k];
}
if ((P.charAt(k) + "").equals(P.charAt(q) + "")){
k = k + 1;
}
pi[q] = k;
}
for(int i = 0; i < pi.length; i++){
System.out.print(pi[i] + " ");
}
}
}
Okay, let's start off by making the code much easier to read. This:
if ((P.charAt(k) + "").equals(P.charAt(q) + ""))
can be simplified to:
if (P.charAt(k) == P.charAt(q))
... and you've done that in multiple places.
Likewise here:
int pi[] = new int[m];
for(int i = 0; i < pi.length; i++){
pi[i] = 0;
}
pi[0] = 0;
... you don't need the explicit initialization. Variables are 0-initialized by default. (It's unclear why you're then setting pi[0] again, although I note that if P.length() is 0, this will throw an exception.)
Next is to remove the explicit comparison with false, instead just using ! so we have:
while(k > 0 && P.charAt(k) != P.charAt(q))
Finally, let's restructure the code a bit to make it easier to follow, use more conventional names, and change int pi[] to the more idiomatic int[] pi:
class Main {
public static void main(String[] args) {
String x = "ababbabbabbababbabb";
int[] prefix = computePrefix(x);
System.out.println("Prefix series for " + x);
for (int p : prefix) {
System.out.print(p + " ");
}
System.out.println();
}
public static int[] computePrefix(String input) {
int[] pi = new int[input.length()];
int k = 0;
for(int q = 2; q < input.length(); q++) {
while (k > 0 && input.charAt(k) != input.charAt(q)) {
k = pi[k];
}
if (input.charAt(k) == input.charAt(q)) {
k = k + 1;
}
pi[q] = k;
}
return pi;
}
}
That's now much easier to follow, IMO.
We can now look back to the pseudocode and see that it appears to be using 1-based indexing for both arrays and strings. That makes life slightly tricky. We could mimic that throughout the code, changing every array access and charAt call to just subtract 1.
(I've extracted the common subexpression of P[q] to a variable target within the loop.)
public static int[] computePrefix(String input) {
int[] pi = new int[input.length()];
int k = 0;
for (int q = 2; q <= input.length(); q++) {
char target = input.charAt(q - 1);
while (k > 0 && input.charAt(k + 1 - 1) != target) {
k = pi[k - 1];
}
if (input.charAt(k + 1 - 1) == target) {
k++;
}
pi[q - 1] = k;
}
return pi;
}
That now gives your desired results, but it's really ugly. We can shift q very easily, and remove the + 1 - 1 parts:
public static int[] computePrefix(String input) {
int[] pi = new int[input.length()];
int k = 0;
for (int q = 1; q < input.length(); q++) {
char target = input.charAt(q);
while (k > 0 && input.charAt(k) != target) {
k = pi[k - 1];
}
if (input.charAt(k) == target) {
k++;
}
pi[q] = k;
}
return pi;
}
It's still not entirely pleasant, but I think it's what you want. Make sure you understand why I had to make the changes I did.
public static int[] computePrefix(String input) {
int[] pi = new int[input.length()];
pi[0] = -1;
int k = -1;
for (int q = 1; q < input.length(); q++) {
char target = input.charAt(q);
while (k > 0 && input.charAt(k + 1) != target) {
k = pi[k];
}
if (input.charAt(k + 1) == target) {
k++;
}
pi[q] = k;
}
return pi;
}

Java permutations 2

I asked a question on helping me with this question about a week ago
Java permutations
, with a problem in the print permutation method. I have tidied up my code and have a working example that now works although if 5 is in the 5th position in the array it doesn't print it. Any help would be really appreciated.
package permutation;
public class Permutation {
static int DEFAULT = 100;
public static void main(String[] args) {
int n = DEFAULT;
if (args.length > 0)
n = Integer.parseInt(args[0]);
int[] OA = new int[n];
for (int i = 0; i < n; i++)
OA[i] = i + 1;
System.out.println("The original array is:");
for (int i = 0; i < OA.length; i++)
System.out.print(OA[i] + " ");
System.out.println();
System.out.println("A permutation of the original array is:");
OA = generateRandomPermutation(n);
printArray(OA);
printPermutation(OA);
}
static int[] generateRandomPermutation(int n)// (a)
{
int[] A = new int[n];
for (int i = 0; i < n; i++)
A[i] = i + 1;
for (int i = 0; i < n; i++) {
int r = (int) (Math.random() * (n));
int swap = A[r];
A[r] = A[i];
A[i] = swap;
}
return A;
}
static void printArray(int A[]) {
for (int i = 0; i < A.length; i++)
System.out.print(A[i] + " ");
System.out.println();
}
static void printPermutation(int[] p)
{
int n = p.length-1;
int j = 0;
int m;
int f = 0;
System.out.print("(");
while (f < n) {
m = p[j];
if (m == 0) {
do
f++;
while (p[f] == 0 && f < n);
j = f;
if (f != n)
System.out.print(")(");
}
else {
System.out.print(" " + m);
p[j] = 0;
j = m - 1;
}
}
System.out.print(" )");
}
}
I'm not too crazy about
int n = p.length-1;
followed by
while (f < n) {
So if p is 5 units long, and f starts at 0, then the loop will be from 0 to 3. That would seem to exclude the last element in the array.
You can use the shuffle method of the Collections class
Integer[] arr = new Integer[] { 1, 2, 3, 4, 5 };
List<Integer> arrList = Arrays.asList(arr);
Collections.shuffle(arrList);
System.out.println(arrList);
I don't think swapping each element with a random other element will give a uniform distribution of permutations. Better to select uniformly from the remaining values:
Random rand = new Random();
ArrayList<Integer> remainingValues = new ArrayList<Integer>(n);
for(int i = 0; i < n; i++)
remainingValues.add(i);
for(int i = 0; i < n; i++) {
int next = rand.nextInt(remainingValues.size());
result[i] = remainingValues.remove(next);
}
Note that if order of running-time is a concern, using an ArrayList in this capacity is n-squared time. There are data-structures which could handle this task in n log n time but they are very non-trivial.
This does not answer the problem you have identified.
Rather i think it identifies a mistake with your generateRandomPermutation(int n) proc.
If you add a print out of the random numbers generated (as i did below) and run the proc a few times it allows us to check if all the elements in the ARRAY TO BE permed are being randomly selected.
static int[] generateRandomPermutation(int n)
{
int[] A = new int[n];
for (int i = 0; i < n; i++)
A[i] = i + 1;
System.out.println("random nums generated are: ");
for (int i = 0; i < n; i++) {
int r = (int) (Math.random() * (n));
System.out.print(r + " ");
Run the proc several times.
Do you see what i see?
Jerry.

Categories

Resources