Got stuck on quite simple problem in my code. I need to count what I would call a nested sums of an array. Let's take as an example the array:
[1,2,2,3,6]
I want to sum them as:
0 + 1 = 1
1 + 2 = 3
1 + 2 + 2 = 5
1 + 2 + 2 + 3 = 8
1 + 2 + 2 + 3 + 6 = 14
sum = 1 + 3 + 5 + 8 + 14 = 31
Edit:
I tried to do it with stack, but it failed
int sums = 0;
Stack<int> sum = new Stack<int>();
for (int i = 0; i < queries.Length; i++)
{
sum.Push(queries[i]);
}
for (int i = 0; sum.Count != 0; i++)
{
if(i != 0)
{
sums += sum.Pop();
}
}
You can run this task in a single loop considering when you have an array of size 5, the first element is repeating 5 times, second element repeating 4 times and etc.
int[] arr = { 1, 2, 2, 3, 6 };
int mysum = 0;
for (int i = 0; i < arr.Length; i++)
mysum += (arr.Length - i) * arr[i];
Console.WriteLine(mysum);
Output:
31
Explanation:
1 = 1
1 + 2 = 3
1 + 2 + 2 = 5
1 + 2 + 2 + 3 = 8
1 + 2 + 2 + 3 + 6 = 14
========================
5*1 + 4*2 + 3*2 + 2*3 + 1*6 = 31
You can do this much more efficiently and more easily, by multiplying each value by its reversed index + 1
For example, using LINQ
int[] arr = { 1, 2, 2, 3, 6 };
var result = arr.Reverse().Select((val, i) => val * (i + 1)).Sum();
Note that .Reverse on an array (or other Collection<T>) does not actually move any items, it just reads them backwards. So this is therefore an O(n) operation, as opposed to your original solution which is O(n2 / 2)
dotnetfiddle
You can also do this procedurally, this is almost the same as #aminrd's answer.
int[] arr = { 1, 2, 2, 3, 6 };
var result = 0;
for (var i = arr.Length - 1; i >= 0; i--)
result += arr[i] * (i + 1);
Take advantage of Linq! .Sum() will add up everything in your collection. You run that twice, once per each slice, and once per each subtotal.
var input = new [] { 1, 2, 2, 3, 6 };
var totalSum = Enumerable.Range(1, input.Length).Sum(len => input[0..len].Sum());
// totalSum is 31
Enumerable.Range gets you a collection of numbers between (and including) 1 and 5 - the possible lengths of each slice of your sub arrays. You then use the range operator [0..#] to get increasingly larger slices.
Yes, this is not as clever as aminrd's solution - it's doing all the computations manually and you're performing many slices.
Related
For Example - If given array is :-
int[] arr = { 1, 4, 8, 3 };
The result Subarray should be:
1 ,
1 ,4 ,
1 ,4 ,8 ,
1 ,4 ,8 ,3 ,
4 ,
4 ,8 ,
4 ,8 ,3 ,
8 ,
8 ,3 ,
3 ,
and than , Maximum of each subarray are :- 1 ,4 ,8,8,4,8,8,8,8,3
therefore sum of all maximum should be :- 1 + 4 +8+8+4+8+8+8+8=3 = 60
To Write Subarray, I was able to do this with loop:-
{
for(int j = i ; j <= n ; j++)
{
for(int k = i ; k < j ; k++)
{
Console.Write(arr[k] + " ," );
}
Console.WriteLine(" " );
}
}
}
After this, I was trying to store maximum values in the Dictionary data structure but was not able to find where exactly use dictionary structure and how to use Math.max statement.
IDictionary<int, int> maxValue = new Dictionary<int, int>();
If you would only need the sum, then it could be solved in O(n). Because you need to print the sub-arrays this is not possible. But it also makes it pretty easy (I don't know C#, replace the print with what you need):
int total = 0;
for (int start = 0; start < n; start++) {
for (int end = start + 1; end <= n; end++) {
int max = arr[start];
print(arr[start]);
for (int i = start + 1; i < end; i++) {
print(", " + arr[i]);
if (arr[i] > max)
max = arr[i];
}
total += max;
print("\n");
}
print("\n");
}
print(total); // or whatever you want to do with it
This avoids the last comma, but you can switch it back if you want to. Also readable variable names can be helpful.
end is not inclusive, I prefer it that way because then you could get the length of the sub-array with end - start. E.g. Java's substring works exactly the same.
I was able to get my array to sort to the right but, struggling
to get the left rotation to work for example [1, 2, 3, 4, 5, 6, 7, 8] if
rotated to the left 4 spaces [4, 5, 6, 7, 8, 1, 2, 3] I feel like it's super simple and just a small change to my current right rotation but, I'm stumped.
if (direction == "right")
{
{
//make spaces<nums.Length
if (spaces > newArray.Length)
{
while (spaces - newArray.Length >= 0)
{
spaces = spaces - newArray.Length;
}
}
if (spaces == 0)
{
}
else
{
int[] temp = new int[spaces];
//move to a temp array
for (var i = temp.Length - 1; i >= 0; i--)
{
temp[i] = newArray[newArray.Length - spaces + i];
}
//push to the end
for (var j = newArray.Length - spaces - 1; j >= 0; j- -)
{
newArray[j + spaces] = newArray[j];
}
//put the ones in temp array back to the top
for (var s = 0; s < temp.Length; s++)
{
newArray[s] = temp[s];
}
}
}
}
Wel, if you want it simple, try Linq and modulo arithmetics:
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int shift = 4;
int[] result = Enumerable
.Range(0, array.Length)
.Select(i => array[(i + shift % array.Length + array.Length) % array.Length])
.ToArray();
Same modulo arithmetics and no Linq
int shift = 4;
int[] result = new int[array.Length];
for (int i = 0; i < result.Length; ++i)
result[i] = array[(i + shift % array.Length + array.Length) % array.Length];
If you want to rotate to right, assign negative values to shift.
Edit: what's going under the hood, modulo arithmetics explained. Our task is when we are given i (index of result) to compute index of the initial array:
array = {1 2 3 4 5 6 7 8}
result = {5 6 7 8 1 2 3 4}
as we can see,
index = i + shift
when shift is small enough (5 is taken from 0 + 4 == 4th index). However we can't exceed arrays length but should subtract it (i.e. restart from 0)
7 + 4 == 11 -> 11 - 8 == 3
I.e.
index = i + shift
index >= array.Length
? index - array.Length // index is too large, restart from 0
: index; // index is small enough
This operation is equal to remainder %:
index = (i + shift) % array.Length
It's good enough, but we still have 2 specific issues with .Net:
i + shift can result in integer oveflow (when, say shift = int.MaxValue)
.Net can well return negative remainder (if shift < 0)
That's why shift % array.Length to meet the first issue and + array.Length for the second. Finally
(i + shift % array.Length + array.Length) % array.Length
Write a program that fills a 15-byte array with positive double-digit random numbers. in each number, the sum of the two digits is equal to 9.
Here's what I've done so far:
int one = 0;
int two = 0;
int[] arr = new int[15];
Random rnd = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr[i] = rnd.Next(10, 99);
one = arr[0] % 10;
two = arr[0] / 10;
if (arr[i] % 2 == 0 && one + two == 9)
Console.WriteLine(arr[i]);
}
The problem with your solution is that rnd.Next(10, 99) will not always produce number with the properties that you want. you should write a code that always works.
We know that sum of digits of a number should be 9. if we assume our two-digit number to be a*10+b where a and b are digits and a + b = 9, we can randomly generate a from 1 to 9.
Then we can calculate other digit b = 9 - a.
therefor our final result would be a*10 + 9 - a which will be simplified to a*9 + 9 where a is random number from 1 to 9, here are two examples.
a=7 then 7 * 9 + 9 = 72, 7 + 2 = 9
a=3 then 3 * 9 + 9 = 36, 3 + 6 = 9
note that a is in this range 1 <= a < 9
How could I go about, lets say for example outputting 3 elements of an array per line on the console? And doing this for the whole array? Is there anything like the Java Scanner that could help me?
You can do some thing like this. It will print elements in a single line and will go to new line after printing three elements in a row.
for(int i=0; i<arr.Length; ++i) {
Console.Write(arr[i]+" ");
if((i+1)%3==0){
Console.WriteLine("");
}
}
Linq solution:
int[] data = Enumerable.Range(1, 20).ToArray();
int groupSize = 3;
var result = Enumerable
.Range(0, data.Length / groupSize +
(data.Length % groupSize == 0 ? 0 : 1))
.Select(index => data.Skip(index * groupSize).Take(groupSize))
.Select(items => string.Join(", ", items));
Console.Write(string.Join(Environment.NewLine, result));
Output:
1, 2, 3
4, 5, 6
7, 8, 9
10, 11, 12
13, 14, 15
16, 17, 18
19, 20
Let arrayElements be the input, then you can group them into chunks of specified size and collect values from each groups and display it:
List<int> arrayElements = new List<int>() { 1,5,2,3,6,4,87,96,54,5,4,5,6,2,5,9,5,5,5,6,2,45,6};
int chunkSize = 3;
var results = arrayElements.Select((x, i) => new { Key = i / chunkSize , Value = x })
.GroupBy(x => x.Key, x => x.Value)
.Select(x=>String.Join(" ",x.ToList()))
.ToList();
foreach (string chunk in results)
{
Console.WriteLine(chunk);
}
Working Example
One way to do this would be with a for loop. You could use something like the following:
// input already defined as array
for (int i = 0; i < input.Length; i += 3) {
Console.WriteLine(input[i] + ' ' + input[i + 1] + ' ' + input [i + 2]);
}
This would require that your array had a length that was a multiple of three; if this wasn't the case, you'd need to add some sort of logic checking that input[i + 1] and input[i + 2] existed within the array.
A possible, albeit somewhat verbose solution, would be like so:
for (int i = 0; i < input.Length; i += 3) {
if (i + 2 >= input.length) {
Console.WriteLine(input[i] + ' ' + input[i + 1] + ' ' + input[i + 2]);
} else if (input[i + 1] >= input.length) {
Console.WriteLine(input[i] + ' ' + input[i + 1]);
} else {
Console.WriteLine(input[i]);
}
}
I've being trying for some time now to find all the elements (including non-consecutive) of an array that sum up to specific value:
using System;
namespace ProgrammingBasics
{
class Exercise
{
static void Main()
{
PrintArray(arr);
SubarrayWithSum();
}
//--------------------------------------------------------------------
/*
Data members.
*/
// targer array
static int[] arr = { 2, 1, 2, 4, 3, 5, 2, 6 };
// target sum
static int sum = 14;
//--------------------------------------------------------------------
/*
Method: IsSubarrayWithSum(arr, sum);
It returns a bool value that indicates
whether there is a subarray within arr
with elements that sum up to specific value.
*/
static void SubarrayWithSum()
{
int depth = 0;
int startIndex = 0;
int endIndex = 1;
CheckAllCombinations(new int[arr.Length], startIndex, endIndex, depth);
}
//--------------------------------------------------------------------
/*
Method: CheckAllCombinations(subarray, sum);
*/
static void CheckAllCombinations(int[] subarray, int startIndex, int endIndex, int depth)
{
if (depth >= arr.Length)
{
return;
}
//Console.ReadKey();
for (int i = startIndex; i < endIndex; i++)
{
subarray[i] = arr[i];
//Console.WriteLine("startIndex = {0}, depth = {1}, i = {2}", startIndex, depth, i);
if (IsWantedSum(subarray))
{
Console.Write("S = {0} -> yes", sum);
PrintSubArray(subarray);
}
//PrintArray(subarray);
//Console.ReadKey();
CheckAllCombinations(new int [arr.Length], startIndex += 1, endIndex = (endIndex < arr.Length)? endIndex + 1 : endIndex, depth += 1);
}
}
//--------------------------------------------------------------------
/*
Method: IsWantedSum(int[] arr)
*/
static bool IsWantedSum(int[] arr)
{
int currentSum = 0;
for (int i = 0; i < arr.Length; i++)
{
currentSum += arr[i];
}
if (currentSum == sum)
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------
/*
Method: PrintArray();
*/
static void PrintArray(int[] subarray)
{
Console.Write("{");
for (int i = 0; i < subarray.Length; i++)
{
Console.Write(subarray[i]);
if (i < subarray.Length -1) Console.Write(", ");
}
Console.WriteLine("}");
}
//--------------------------------------------------------------------
/*
Method: PrintSubArray();
*/
static void PrintSubArray(int[] subarray)
{
Console.Write("(");
for (int i = 0; i < subarray.Length; i++)
{
if (subarray[i] != 0)Console.Write(subarray[i]);
if (subarray[i] != 0 && i < subarray.Length - 1) Console.Write(" + ");
}
Console.WriteLine(" = {0})", sum);
}
}
}
I'm getting somewhat partially right result:
{2, 1, 2, 4, 3, 5, 2, 6}
S = 14 -> yes(4 + 3 + 5 + 2 + = 14)
S = 14 -> yes(2 + 4 + 3 + 5 + = 14)
S = 14 -> yes(4 + 3 + 5 + 2 + = 14)
S = 14 -> yes(4 + 3 + 5 + 2 + = 14)
S = 14 -> yes(2 + 4 + 3 + 5 + = 14)
S = 14 -> yes(4 + 3 + 5 + 2 + = 14)
with duplications and missing sub-arrays of non-consecutive elements such as:
yes (1 + 2 + 5 + 6 = 14)
Could someone give me a hint on the problems of my algorithm and probably suggest a correction / new implementation?
Here's a simple way to do it with combinations. There's probably a better way to store them (I'm thinking using a dictionary to encode all the sub sums you already have). At the end of the day, if you want to account for non-consecutive elements, you're going to have to get the sub arrays that are possible in this case, and not just look at consecutive choices. Credit for the combination algorithm goes to ojlovecd here .
class Exercise
{
static void Main()
{
PrintArray(arr);
// SubarrayWithSum();
var result = GetCombination(arr);
foreach(var list in result)
{
var total = list.Sum();
if (total == sum)
PrintArray(list);
}
}
static List<int> arr = new List<int> { 2, 1, 2, 4, 3, 5, 2, 6 };
static int sum = 14;
static List<List<int>> GetCombination(List<int> list)
{
var result = new List<List<int>>();
result.Add(new List<int>());
double count = Math.Pow(2, list.Count);
for (int i = 1; i <= count - 1; i++)
{
string str = Convert.ToString(i, 2).PadLeft(list.Count, '0');
for (int j = 0; j < str.Length; j++)
{
if (str[j] == '1')
{
result[i - 1].Add(list[j]);
}
}
result.Add(new List<int>());
}
return result;
}
static void PrintArray(List<int> subarray)
{
Console.Write("{");
for (int i = 0; i < subarray.Count; i++)
{
Console.Write(subarray[i]);
if (i < subarray.Count - 1) Console.Write(", ");
}
Console.WriteLine("}");
}
}
I think the duplicates are occurring because you have zeroes in the array that you are adding. See updated code which runs quicker.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ProgrammingBasics
{
class Exercise
{
static void Main()
{
PrintArray(arr);
SubarrayWithSum();
}
//--------------------------------------------------------------------
/*
Data members.
*/
// targer array
static int[] arr = { 2, 1, 2, 4, 3, 5, 2, 6 };
// target sum
static int sum = 14;
//--------------------------------------------------------------------
/*
Method: IsSubarrayWithSum(arr, sum);
It returns a bool value that indicates
whether there is a subarray within arr
with elements that sum up to specific value.
*/
static void SubarrayWithSum()
{
int depth = 0;
int endIndex = arr.Length - 1;
CheckAllCombinations(new int[arr.Length], depth);
}
//--------------------------------------------------------------------
/*
Method: CheckAllCombinations(subarray, sum);
*/
static void CheckAllCombinations(int[] subarray, int depth)
{
//Console.ReadKey();
for (int i = depth; i < arr.Length; i++)
{
subarray[depth] = arr[i];
Console.WriteLine("depth = {0}, i = {1}, array = '{2}' ", depth, i, string.Join(",", subarray.Select(x => x.ToString()).ToArray()));
int currentSum = subarray.Take(depth + 1).Sum();
if (currentSum == sum)
{
Console.Write("S = {0} -> yes : ", sum);
Console.WriteLine(string.Join(",", subarray.Take(depth + 1)));
}
//PrintArray(subarray);
//Console.ReadKey();
if (currentSum < sum)
{
CheckAllCombinations(subarray, depth + 1);
}
}
}
//--------------------------------------------------------------------
/*
Method: IsWantedSum(int[] arr)
*/
//--------------------------------------------------------------------
/*
Method: PrintArray();
*/
static void PrintArray(int[] subarray)
{
Console.Write("{");
for (int i = 0; i < subarray.Length; i++)
{
Console.Write(subarray[i]);
if (i < subarray.Length - 1) Console.Write(", ");
}
Console.WriteLine("}");
}
//--------------------------------------------------------------------
/*
Method: PrintSubArray();
*/
static void PrintSubArray(int[] subarray)
{
Console.Write("(");
for (int i = 0; i < subarray.Length; i++)
{
if (subarray[i] != 0) Console.Write(subarray[i]);
if (subarray[i] != 0 && i < subarray.Length - 1) Console.Write(" + ");
}
Console.WriteLine(" = {0})", sum);
}
}
}
OK, here is small attempt to briefly describe the info that I went through to understand the problem1 and implement a basic solution.
It turns out that The Subset Sum Problem is considered a special case of the Knapsack Problem in which we are searching to maximize profit while keeping value called weight under specific capacity, but in our case the profit and weight associated with each value are identical.
There are variety of great solutions described in "Knapsack Problems" - Keller, Pferschy, Pisinger, however, for the time being the simplest solution that I could implement and understand, not carrying about complexity and / or efficacy, looks like this:
//--------------------------------------------------------------------
/*
Method: FindSubArray();
Base case: - if current sum == targer sum: print current elements.
- if index == arr.Length: terminate search.
Recursive step:
- do not/select element with index and do not/update the current sum; recursive call with updated current sum and index.
*/
static void FindSubArray(int index, int currentSum, bool[] subArray)
{
// base case
if (currentSum == targetSum)
{
PrintSubArray(subArray);
}
else if (index == arr.Length)
{
return;
}
else
{
// recursive calls
subArray[index] = true;
currentSum += arr[index];
FindSubArray(index + 1, currentSum, subArray);
currentSum -= arr[index]; // restore previous value of the sum signifying: element not selected
subArray[index] = false;
FindSubArray(index + 1, currentSum, subArray);
}
}
where PrintSubArray(subArray); prints all the elements of arr marked with true in subArray.
Output:
{2, 1, 2, 4, 3, 5, 2, 6}
S = 14 -> yes (2 + 1 + 2 + 4 + 3 + 2 + = 14)
S = 14 -> yes (2 + 1 + 2 + 4 + 5 + = 14)
S = 14 -> yes (2 + 1 + 2 + 3 + 6 = 14)
S = 14 -> yes (2 + 1 + 4 + 5 + 2 + = 14)
S = 14 -> yes (2 + 1 + 3 + 2 + 6 = 14)
S = 14 -> yes (2 + 1 + 5 + 6 = 14)
S = 14 -> yes (2 + 2 + 4 + 6 = 14)
S = 14 -> yes (2 + 2 + 3 + 5 + 2 + = 14)
S = 14 -> yes (2 + 4 + 3 + 5 + = 14)
S = 14 -> yes (2 + 4 + 2 + 6 = 14)
S = 14 -> yes (1 + 2 + 4 + 5 + 2 + = 14)
S = 14 -> yes (1 + 2 + 3 + 2 + 6 = 14)
S = 14 -> yes (1 + 2 + 5 + 6 = 14)
S = 14 -> yes (1 + 4 + 3 + 6 = 14)
S = 14 -> yes (1 + 5 + 2 + 6 = 14)
S = 14 -> yes (2 + 4 + 3 + 5 + = 14)
S = 14 -> yes (2 + 4 + 2 + 6 = 14)
S = 14 -> yes (4 + 3 + 5 + 2 + = 14)
S = 14 -> yes (3 + 5 + 6 = 14)
The book that I'm reading states the problem simply as: "Find if there is a sub array with elements that sum up to specific value'.