this question is related to this post: https://stackoverflow.com/a/35810542/5888956
Basically, I have to write a program that reads in the integer from the keyboard, and it has to be able to display 50! using only array. (cannot use Biginteger or anything)
I got this so far, thanks to the help from the previous post.
import java.util.Scanner;
class Factorial
{
public static void main(String[] args)
{
int n;
Scanner kb = new Scanner(System.in);
System.out.println("Enter n");
n = kb.nextInt();
int [] result = fact(n);
int i = result.length-1;
while (i > 0 && result[i] == 0)
{
i--;
}
System.out.print(n + "! = ");
while (i >= 0)
{
System.out.print(result[i--]);
}
System.out.println();
}
public static int[] fact(int n)
{
int[] a = new int[100];
a[0] = 1;
for (int i = 1; i <= n; i++)
{
int carry = 0;
for(int j = 0; j < a.length; j++)
{
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
return a;
}
}
But I can't still understand the logic behind here.
Especially, this part,
for (int i = 1; i <= n; i++)
{
int carry = 0;
for(int j = 0; j < a.length; j++)
{
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
I'm trying to solve this with pen and paper, so that I can understand it completely. (of course with the small number like 4!)
So if I type 4 for n, 4! is 24 (4*3*2*1).
In my logic, when i is 1 a[0] is 1 because I initialized above, but after the for loop ends once, does it become 0?
i = 1, j = 0
x = a[0] * 1 + 0 = 1
a[0] = 0
carry = 1
// ------repeat the loop
i = 2, j = 0
x = a[0] * 1 + 1 = 1
a[0] = 0
carry = 1
So it is apparently not the right logic, I think.
Can someone please please help me to understand this?
The factorial operation just means multiplying a whole bunch of numbers, so conceptually, it is not a difficult operation to implement. The reason why it quickly becomes a problem when implementing in code, is that it produces huge numbers, in fact, too large to be held in one int (4 bytes) or even long (8 bytes) variables (12! is the max you could hold in an int). Otherwise, we would just do something like:
int fact = 1;
for(int i = 2 ; i <= n ; i++) {
fact *= i;
}
So one way to deal with this is to treat a number as an "array of digits", in base 10. For example, the number 2016 could be treated like this array: int[] digits = {2, 0, 1, 6}, which is just another way of saying 2016 = 2*1000 + 0*100 + 1*10 + 6*1.
Now let's imagine that we have 8-bits computers, and we can't represent numbers larger than 255 (or pow(2,8)-1). We wouldn't be able to simply do 2016*2 directly, but, because multiplication is distributive a(b+c) = ab+ac, we could decompose the multiplication of the "large" number 2016 into smaller multiplications like so:
2016 → {2, 0, 1, 6} → 2*1000 + 0*100 + 1*10 + 6
2016 * 2 = (2*1000 + 0 + 1*10 + 6) * 2 = (2*2)*1000 + (2*0) + (2*1)*10 + (2*6)
Now we can do these small multiplications like you would by hand:
2016 * 2 → {2, 0, 1, 6} * 2 → {2*2, 0*2, 1*2, 6*2} → {4, 0, 2, 12}
We get 12 for the first digit, so we need the carry over the 1:
{4, 0, 2, 12} → {4, 0, 2+1, 2} → {4, 0, 3, 2} = 4032
That's exactly what your code does:
a[0] = 1;
for (int i = 1; i <= n; i++) {
int carry = 0;
for(int j = 0; j < a.length; j++) {
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
It takes your number or "array of digits" a, and multiplies the digits a[j] individually by i → x = a[j] * i. If it's bigger than 9, take the extra to carry it to the next digit → carry = x / 10, and you're left with the remnant as the value of the digit → a[j] = x % 10.
Related
I want to get n from user and subtract the largest possible number from the Fibonacci sequence by decreasing it in sequence and continue this process until it reaches zero. Our Fibonacci sequence starts from 1. The number 88 can be The form 1 + 3 + 8 + 21 + 55 wrote that these numbers are the sentences 1, 3, 5, 7 and 9 of the Fibonacci sequence, respectively.
Input: 88
Output: 9 7 5 3 1
My code:
class Main {
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[] fibo = new int[1000];
int[] arr = new int [100];
int d = 0;
int b = 0;
fibo[1] = 1;
fibo[2] = 2;
for (int i = 3, j = 1; i <= 20; i++, j++)
fibo[i] = fibo[i - 1] + fibo[i - 2];
b = n;
for (int i = 1, j = 1; i <= 20 && b >= 0; i++, j++) {
if (b == fibo[i] || b + 1 == fibo[i] || b - 1 == fibo[i]) {
d = i;
b -= fibo[d - 1];
System.out.println("B= " + b);
arr[j] = d - 1;
System.out.println("arr= " + arr[j]);
}
}
}
}
The first problem is that, every time you subtract something from your number, the next number you will subtract will have to be smaller - because your number itself is smaller now - whereas in your code, the numbers just keep getting bigger.
For instance, after you try the 9th fibonacci number 55, you are trying 89, whereas you should be trying 34.
This can be solved by iterating backwards through the fibonacci numbers, as in starting from the biggest number at the end of the array, so that as the loop iterates, the numbers get smaller.
The second problem is your check in the if statement, which is only satisfied if there happens to be a fibonacci number very close to the number you are at.
Instead, if you want to select the largest fibonacci number that is smaller than your number, you can just check for the 'smaller than your number' part, since 'the largest fibonacci' part is already taken care of by how the for loop works.
Here is the working code. You will also notice a lot fewer variables. Also I hard-coded the input number for testing, you'll have to add the scanner stuff back in. Sorry.
public class Main {
public static int len = 20; // the program considers this many fibonacci numbers
public static void main(String args[])
{
int n = 88;
int[] fibo = new int[len];
for(int i=0; i<len; i++)
{
if (i < 2) fibo[i] = i+1; // for 1 and 2
else fibo[i] = fibo[i-1] + fibo[i-2]; // for 3 and 5 and ...
}
for(int i=len-1; i>=0; i--)
{
if (fibo[i] <= n)
{
System.out.format("%d: %d - %d = %d\n",
i+1, // to correct for 0-indexing
n, fibo[i], n-fibo[i]);
n -= fibo[i];
}
}
}
}
So, for example i have an array: int[] {1,2,3,4,5}. I need to print the product of even positions, 0 position will be considered even, so it will be: 1 * 3 * 5 = 15.
When I am summing an array, I am doing something like this:
int sum = 0;
for (int i = 0; i < arr.length; sum += arr[i++])
and I am receiving the answer correct.
Now, I thought of using the same method for getting the product:
int produs = 1;
for (int i = 0; i < arr.length; produs *= arr[i = i + 2])
Here I always get an error. I don't know why, but if I am doing:
int produs = 1;
for (int i = 0; i < arr.length; i++) {
if ( (i & 1) == 0) {
produs *= arr[i];
}
}
or
int produs = 1;
for (int i = 0; i < arr.length; i = i + 2) {
produs *= arr[i];
}
I am also getting correct answer.
so, my question is why my method with inline for does not work?
int produs = 1;
for (int i = 0; i < arr.length; produs *= arr[i = i + 2])
this one.
If you perform a suffix increment operation, the compiler puts the old value on the stack, e.g.
int[] arr = new int[] { 0, 10, 20, 30 };
int i = 0;
int x = arr[i++]; // x will be 0, i is incremented to 1
On the other hand, if you would use a prefix increment operation, the compiler puts the new value on the stack, e.g.
int[] arr = new int[] { 0, 10, 20, 30 };
int i = 0;
int x = arr[++i]; // x will be 10, i is incremented to 1
Lastly, a variable assignment operation puts the resulting value on the stack, e.g.
int[] arr = new int[] { 0, 10, 20, 30 };
int i = 0;
int x = arr[i = i + 3]; // x will be 30, i is increased by 3
Therefore, if you use arr[i = i + 2] as post-block statement, you actually access the following array elements: 2, 4, 6, yielding an ArrayIndexOutOfBoundsException.
I strongly recommended (also for the sake of readability) that you restructure your algorithm to use the for-block to do the actual calculation and to use the post-block statement to increase the variable i:
for (int i = 0; i < arr.length; i+=2) {
// TODO Calculation
}
You run into an ArrayIndexOutOfBoundsException, because you try to access an element beyond the array boundary. That is because the condition i < arr.length will not be checked when you do produs *= arr[i = i + 2] in the last section of the for-loop.
You can just split up your code inside the increment section, in fact you can chain as many statements in there as you wish, you just have to separate them with a comma ,:
int produs = 1;
for (int i = 0; i < arr.length; produs *= arr[i], i += 2);
The reason you cannot implement a for-loop like this inline is that in the incremental part produs *= arr[i = i + 2] you will have i reaching an index out of the bound of your array because it jumps through 2 steps. Basically in its final iteration, i will reach value of 6 which is out of the indices of your array (the final index of your array is 4) and the part produs *= arr[i = i + 2] will produce an error.
In this case, it is better to use the way that worked for you:
int produs = 1;
for (int i = 0; i < arr.length; i = i + 2) {
produs *= arr[i];
}
You always instantiate your produs with 0.
If you multiply something with zero, than it will be zero.
You have to instantiate it with 1, then should your last example work
int produsOfEven(int[] array) {
int produs = 1;
// step by 2
for (int i = 0; i < array.length; i += 2) {
produs *= array[i];
}
return produs;
}
Edit
To your question, why the last example wont work: As already pointed out in the comments, your condition will be checked to "late".
Let us imagine you have the code for (int i = 0; i < arr.length; produs *= arr[i = i + 2]) and array of length 3. Then this steps will be computed:
Init i with 0.
Check condition i < arr.length, it is true.
Exec body - no body, nothing will happen.
Increase i by running produs *= arr[i = i + 2], i is now 2, produs is changed by array-index 2.
Check condition i < arr.length, it is true.
Exec body - no body, nothing will happen.
Increase i by running produs *= arr[i = i + 2], i is now 4, produs is changed by array-index 4. ArrayIndexOutOfBoundsException was thrown.
You had better use stream
java.util.concurrent.atomic.AtomicInteger index = new java.util.concurrent.atomic.AtomicInteger();
int produs = java.util.Arrays.stream(new int[] {1,2,3,4,5})
.filter(i -> index.getAndIncrement() % 2 == 0).reduce(1, (a, b) -> a * b);
I just took this sample test, and it's right for the most part, but I am not sure why I would get the two cases wrong.
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], A1, ..., A[P − 1] and A[P], A[P + 1], ...,
A[N − 1].
The difference between the two parts is the value of: |(A[0] + A1 +
... + 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.
For example, consider array A such that:
A[0] = 3 A1 = 1 A[2] = 2 A[3] = 4 A[4] = 3 We can split
this tape in four places:
P = 1, difference = |3 − 10| = 7 P = 2, difference = |4 − 9| = 5 P =
3, difference = |6 − 7| = 1 P = 4, difference = |10 − 3| = 7 Write a
function:
class Solution { public int solution(int[] A); }
that, given a non-empty zero-indexed array A of N integers, returns
the minimal difference that can be achieved.
For example, given:
A[0] = 3 A1 = 1 A[2] = 2 A[3] = 4 A[4] = 3 the function
should return 1, as explained above.
Assume that:
N is an integer within the range [2..100,000]; each element of array A
is an integer within the range [−1,000..1,000]. Complexity:
expected worst-case time complexity is O(N); expected worst-case space
complexity is O(N), beyond input storage (not counting the storage
required for input arguments).
class Solution {
public int solution(int[] A) {
int sum = 0;
int subtracted = 0;
int minDiff = 100000;
for (int i = 0; i < A.length; i++) {
sum += A[i];
}
for (int i = 0; i < A.length; i++) {
sum -= A[i];
subtracted += A[i];
int diff = (Math.abs(sum - subtracted));
if (minDiff > diff) {
minDiff = diff;
}
}
return minDiff;
}
}
Coldility Result
I wrote in java and achieved 100% on codility
public static int solution(int[] A) {
int sum=0,leftsum=0,rightsum=0,newmin=0,min=0;
for(int i=0;i<A.length;i++){
sum=sum+A[i];
}
for(int i=1;i<A.length;i++){
leftsum=leftsum+A[i-1];
rightsum=sum-leftsum;
//System.out.println(leftsum-rightsum);
if(i==1)
min=newmin=Math.abs(leftsum-rightsum);
else
newmin=Math.abs(leftsum-rightsum);
min=Math.min(min,newmin);
}
return min;
}
Consider this approach using just one for loop: The main idea is to accumulate from left and right at the same time until they cross the middle of the array. At that point, they will start sharing elements in the sum, so you need then to evaluate 2 cases:
1st- subtracting the shared elements from the left side
2nd- subtracting the shared elements from the right side
public int solution(int[] A) {
// write your code in C# 6.0 with .NET 4.5 (Mono)
int l=A.Length;
int mid= l%2>0 ? (l/2) : (l/2)-1;
long ls=0;
long rs=0;
long res=long.MaxValue;
long shared=0;
for(int i=0, j=l-1; i<l; i++, j--){
ls=ls+A[i];
rs=rs+A[j];
if(i>=mid && i<l-1){
if(i==j) shared=A[i];
else if(i>j) shared=shared+A[i]+A[j];
rs=rs-shared;
res= res < Math.Abs(ls-rs) ? res : Math.Abs(ls-rs);
rs=rs+shared;
ls=ls-shared;
res= res < Math.Abs(ls-rs) ? res : Math.Abs(ls-rs);
ls=ls+shared;
}
}
return (int)res;
}
Solved it. Don't use int sum = Arrays.stream(A).sum();, it fails the performance tests. I got all test case right except one with int sum = Arrays.stream(A).sum(); but it timed out on the largest test case. So I changed it to a for loop sum and it passed with 100%.
public int solution(int[] A) {
int result = Integer.MAX_VALUE;
int total = 0;
int sum = 0;
for (int i = 0; i < A.length; i++) {
sum += A[i];
}
for (int i = 0; i < A.length - 1; i++) {
total += A[i];
int toEndSum = sum - total;
int diff = Math.abs(total - toEndSum);
if (diff < result)
result = diff;
}
return result != Integer.MAX_VALUE ? result : 0;
}
`I have following array {9, 0, 2, -5, 7} and from this array i need to find the the square pairs <2, 7> and <7, 9> where first element must be less than second.
And <-5, 9> and <0, 9> are not square pairs, even though they sum to perfect squares,
because both members of a square pair have to be greater than 0.
bool ans;
int[] number = new int[]{9,0,2,-5,7};
for (int j = 0; j < number.Length; j++)
{
if (number[j]<number[j+1])
ans = IsPerfectSquares(number[j]+number[j+1]);
if(ans)
count++;
}
}
public static bool IsPerfectSquares(int input)
{ long SquareRoot = (long)Math.Sqrt(input);
return ((SquareRoot * SquareRoot) == input);
} `
C# Linq:
int[] array = {9, 0, 2, -5, 7};
int len = array.Length;
var pairs =
from i in Enumerable.Range(0, len-1)
where array[i] > 0
from j in Enumerable.Range(i+1, len-i-1)
where array[j] > 0
let sqrt = (int)Math.Sqrt(array[i] + array[j])
where array[i] + array[j] == sqrt * sqrt
select new {
A = Math.Min(array[i], array[j]),
B = Math.Max(array[i], array[j])
};
//or: select new int[] { ... };
Results:
{ A = 7, B = 9 }
{ A = 2, B = 7 }
Java: (also works in C# with slightly different syntax)
int[] array = { 9, 0, 2, -5, 7 };
List<int[]> pairs = new ArrayList<int[]>();
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] <= 0) continue;
for (int j = i + 1; j < array.length; ++j) {
if (array[j] <= 0) continue;
int sqrt = (int)Math.sqrt(array[i] + array[j]);
if (array[i] + array[j] == sqrt * sqrt)
pairs.add(new int[] { array[i], array[j] });
}
}
I will let you write the code.
The algorithm is roughly this:
Iterate over the array. Remove all elements whose value is less than or equal to zero.
Create all possible pairs by using nested loop (two loops). For each pair, take the sum. Let say the sum is S. Take the square root of S. Let say the square root of R. Note that S is an integer (so, it may not exactly the square root of S). Check whether S is a perfect square by checking whether R*R = S.
the aluminium 2014 gives me wrong answer [3 , 9 , -6 , 7 ,-3 , 9 , -6 , -10] got 25 expected 28
but when i repeated the challenge with the same code and make case test it gives me the correct answer
Your test case [3, 9, -6, 7, -3, 9, -6, -10] : NO RUNTIME ERRORS (returned value: 28)
what is the wrong with it ???
the challenge :-
A non-empty zero-indexed array A consisting of N integers is given. A
pair of integers (P, Q), such that 0 ≤ P ≤ Q < N, is called a slice of
array A. The sum of a slice (P, Q) is the total of A[P] + A[P+1] + ...
+ A[Q]. The maximum sum is the maximum sum of any slice of A. For example, consider array A such that: A[0] = 3
A[1] = 2
A[2] = -6
A[3] = 3
A[4] = 1 For example (0, 1) is a slice of A that has sum A[0] + A[1] = 5. This is the maximum sum of A. You can perform a single swap
operation in array A. This operation takes two indices I and J, such
that 0 ≤ I ≤ J < N, and exchanges the values of A[I] and A[J]. To goal
is to find the maximum sum you can achieve after performing a single
swap. For example, after swapping elements 2 and 4, you will get the
following array A: A[0] = 3
A[1] = 2
A[2] = 1
A[3] = 3
A[4] = -6 After that, (0, 3) is a slice of A that has the sum A[0] + A[1] + A[2] + A[3] = 9. This is the maximum sum of A after a single swap. Write a function: class Solution { public int solution(int[] A);
} that, given a non-empty zero-indexed array A of N integers, returns
the maximum sum of any slice of A after a single swap operation. For
example, given: A[0] = 3
A[1] = 2
A[2] = -6
A[3] = 3
A[4] = 1 the function should return 9, as explained above.
and my code is :-
import java.math.*;
class Solution {
public int solution(int[] A) {
if(A.length == 1)
return A[0];
else if (A.length==2)
return A[0]+A[1];
else{
int finalMaxSum = A[0];
for (int l=0 ; l<A.length ; l++){
for (int k = l+1 ; k<A.length ; k++ ){
int [] newA = A;
int temp = newA[l];
newA [l] = newA[k];
newA[k]=temp;
int maxSum = newA[0];
int current_max = newA[0];
for(int i = 1; i < newA.length; i++)
{
current_max = Math.max(A[i], current_max + newA[i]);
maxSum = Math.max(maxSum, current_max);
}
finalMaxSum = Math.max(finalMaxSum , maxSum);
}
}
return finalMaxSum;
}
}
}
i don't know what's the wrong with it ??
It was a bug in the website and this is the reply from the support team
the evaluation system run your program not only on the test case it presented to you, but also on the mirrored test case B = [-10, -6, 9, -3, 7, -6, 9, 3]. On test case B your program indeed returned 22, when it should have returned 28.
public static int findMaxSumOfArray(int[] A) {
int[] T = new int[A.length];
int sum = 0;
int max1 = Integer.MIN_VALUE;
int max2 = Integer.MIN_VALUE;
int max3 = Integer.MIN_VALUE;
int max1index = 0;
int max2intex = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] < 0) {
T[i] = sum;
sum = 0;
} else if (i == A.length - 1) {
sum += A[i];
T[i] = sum;
sum = 0;
} else {
sum += A[i];
}
}
for (int i = 0; i < T.length; i++) {
if (max3 < T[i]) {
if (max2 < T[i]) {
if (max1 < T[i]) {
max2intex = max1index;
max3 = max2;
max2 = max1;
max1 = T[i];
max1index = i;
} else {
max3 = max2;
max2 = T[i];
max2intex = i;
}
} else {
max3 = T[i];
}
}
}
return max1 + max2 + (Math.abs(max1index - max2intex) == 1 ? max3 : 0);
}