C# How to print combinations that add upto given number? - c#

I am trying to implement "Count of different ways to express N as the sum of other numbers" problem with C# using dynamic progamming.
My method looks like:
static int howManyWays(int n)
{
int [] safe= new int[n + 1];
// base cases
safe[0] = safe[1] = safe[2] = 1;
safe[3] = 2;
// iterate for all values from 4 to n
for (int i = 4; i <= n; i++)
safe[i] = safe[i - 1] + safe[i - 3]
+ safe[i - 4];
return safe[n];
}
For example, if i select n as n = 4, then my results are:
4
I want to print out those 4 combinations of sums:
1+1+1+1
1+3
3+1
4
Is there any way to do that either recursively or using dynamic programming?
My try is to get set of combinations recursively :
static int[] Combs(int n)
{
int[] tusc = { };
if (n < 0)
yield break;
if (n == 0)
yield return tusc;
int[] X = { 1, 3, 4 };
for(int i = 0; i < X.Length; i++)
{
for(j = 0; j <= Combs(n-X[i]).Length; j++)
{
yield return X + j;
}
}
}
Original code that works in python, but don't know how to translate into C#:
def combis(n):
if n < 0:
return
if n == 0:
yield []
for x in (1, 3, 4):
for combi in combis(n-x):
yield [x] + combi
>>> list(combis(5))
[[1, 1, 1, 1, 1], [1, 1, 3], [1, 3, 1], [1, 4], [3, 1, 1], [4, 1]]

Here's a pretty direct translation:
using System;
using System.Collections.Generic;
class MainClass
{
static IEnumerable<List<int>> Combs(int n)
{
if (n < 0)
{
yield break;
}
else if (n == 0)
{
yield return new List<int>();
}
foreach (int x in new List<int>() {1, 3, 4})
{
foreach (IEnumerable<int> combi in Combs(n - x))
{
var result = new List<int>() {x};
result.AddRange(combi);
yield return result;
}
}
}
public static void Main(string[] args)
{
foreach (IEnumerable<int> nums in Combs(5))
{
foreach (var i in nums)
{
Console.Write(i + ", ");
}
Console.WriteLine();
}
}
}
Output:
1, 1, 1, 1, 1,
1, 1, 3,
1, 3, 1,
1, 4,
3, 1, 1,
4, 1,
Remarks:
Since you're using yield, change the Combs header to return an IEnumerable<int> rather than int[].
Use lists rather than fixed-length arrays and List.AddRange to translate the + list concatenation operation from Python.
There is some confusion about translating X. In the Python version, x is just a single element in the {1, 3, 4} options list but in the C# version, it's the whole array.
Combs(n-X[i]).Length doesn't make sense--it calls Combs, takes the length of the results and then throws all of the results away, so it's like a really expensive counter. j gives you a counter index, not one of the elements from the child Combs call as intended. foreach is the most accurate translation of Python's for .. in loops.
The {1, 3, 4} list should probably be made into a parameter to allow the caller to control its behavior.
Efficiency is poor because overlapping subproblems are recomputed. Improving it is left as an exercise (this was probably your next step anyway).

Related

How to remove two elements of collection at the same time? Task about cyclopes lenses

I cant solve this task.
There are N cyclopes and an array of N elements.
Every element is eyesight value of single cyclop.
Every cyclop needs a lens with a value K but he will be okay with
lens of value K+1 or K-1.
Cyclopes always buy lenses in pairs.
For example 5 cyclopes with eyesight values [1,-1,2,3,-3] will need to buy 3 pairs of lenses.
I need to write a program that will count minimal amount of lens pairs need.
I tried it like this
int cyclops = 4;
int[] cyclopsSightValues = { 1, 7, 4, 1 };
if (cyclops < 2) { return 1;}
List<int> list = cyclopsSightValues .ToList();
int matchCount = 0;
for (int i = 0; i < list.Count; i++)
{
for (int j = 0; j < list.Count; j++)
{
if (list[i] == list[j] ||
list[i] + 1 == list[j] ||
list[i] + 2 == list[j] ||
list[i] - 1 == list[j] ||
list[i] - 2 == list[j])
{
int valueToRemove1 = list[i];
int valueToRemove2 = list[j];
list.Remove(valueToRemove1);
list.Remove(valueToRemove2);
matchCount++;
continue;
}
}
}
return matchCount + (cyclops-matchCount*2);
I think i need to find matching eyesights and remove them from list, but the result always comes out less then the correct one by 1.
Maybe my logic is wrong altogether?
Any help would be much appreciated.
Look, if two cyclops have eyesight difference 2 or less by absolute value they can buy lenses which fit both of them, e.g.
3 and 1 can buy pair of 2 lenses. Let's try to use greedy approach now: order cyclops by their eye sights and try
to use spare lenses as frequent as we could:
1, -1, 2, 3, -3 -> -3, -1, 1, 2, 3
-3 v -1, 1 v 2, 3
can use
-2 1
So far so good all we have to do is to sort and scan:
private static int Solve(int[] cyclopsSightValues) {
Array.Sort(cyclopsSightValues);
int result = 0;
bool hasSpare = false;
for (int i = 0; i < cyclopsSightValues.Length; ++i)
if (hasSpare && cyclopsSightValues[i - 1] + 2 >= cyclopsSightValues[i])
hasSpare = false; // We use spare lense from the previous cyclope
else {
// we have to buy a pair, and now we have a spare lense
hasSpare = true;
result += 1;
}
return result;
}
Demo:
int[][] tests = {
new[] { 1, -1, 2, 3, -3 },
new int[] { },
new[] { 1, 1, 1, 1 },
};
string report = string.Join(Environment.NewLine, tests
.Select(item => $"[{string.Join(", ", item)}] => {Solve(item)}"));
Console.Write(report);
Output:
[1, -1, 2, 3, -3] => 3
[] => 0
[1, 1, 1, 1] => 2
Please, fiddle yourself
Untested, but should more or less work:
public static IEnumerable<int> LensesToBuy(IEnumerable<int> cyclopsVisions)
{
int? buf = null;
var e = cyclopsVisions.OrderBy(v => v).GetEnumerator();
while(e.MoveNext())
{
if (!buf.HasValue)
{
buf = e.Current;
}
else if (Math.Abs(buf.Value - e.Current) > 2)
{ // cached value not compatible
yield return buf.Value;
buf = e.Current;
}
else
{ // cached value is compatible
if (buf.Value == e.Current) yield return buf.Value;
if (buf.Value > e.Current) yield return buf.Value - 1;
if (buf.Value < e.Current) yield return buf.Value + 1;
buf = null;
}
}
if (buf.HasValue) yield return buf.Value;
}
Call it like this:
int[] cyclopsSightValues = { 1, 7, 4, 1 };
var result = LensesToBuy(cyclopsSightValues); //okay to pass array
Console.WriteLine(result.Count());

C# from array create an non-adjacent subset

I want to create an subset from an array
array =[-2,1,3,-4,5]
I want the subset like this below.
[-2, 3, 5] [-2, 3] [-2, -4] [-2, 5] [1, -4] [1, 5] [3, 5]
-before the elements should be skipped one element
-2,3,5
1 -4
3.5
-then for each element, one neighbor should be skipped and the others taken one by one, forming pairs (without repeating the above)
-2,3
-2, -4
-2.5
1, -4 (do not take above have)
3.5 ((we do not have above)
-1.5
//This is my code.
static void Main(string[] args)
{
int[] kume = { -3, 4, 5, 6, 7};
String[] altkume = new string[10];
String s = "";
for(int m = 0; m<7; m++)
{
int b = m;
s += "[";
for (int j = 0; j < kume.Length; j += 2)
{
if ((b & 1) == 0)
{
s += kume[j].ToString() + ",";
}
b = b >> 1;
}
s += "]" + "\n";
altkume[m] = s;
}
for(int i = 0; i<altkume.Length; i++)
{
Console.WriteLine(altkume[i]);
}
Console.ReadKey();
}
Output:
[-3,5,7,]
[5,7,]
[-3,7,]
[7,]
[-3,5,]
[5,]
[-3,]
But i dont want like this [5,] [-3,] [7,]
I talked about problem. does anyone help ?
I've made a handy extension that will return the output you seek:
public static class Extensions
{
public static IEnumerable<List<T>> GetNonAdjacentSubsets<T>
(
this IEnumerable<T> source, // the collection we are evaluating
int min_distance, // minimum gap between numbers
List<T> subset = null // stores the progress of the subset we are evaluating
)
{
for (int i = 0; i < source.Count(); i++)
{
var new_subset = new List<T>(subset ?? Enumerable.Empty<T>())
{
source.ElementAt(i)
};
if (new_subset.Count > 1) //return subsets of more than one element
yield return new_subset;
if (source.Count() < 2) //end of list reached
yield break;
foreach (var ss in source.Skip(i + min_distance).GetNonAdjacentSubsets(min_distance, new_subset))
yield return ss;
}
}
}
Usage:
var arr = new int[] { -2, 1, 3, -4, 5 };
var subsets = new List<List<int>>(arr.GetNonAdjacentSubsets(2));
Output:
-2, 3
-2, 3, 5
-2, -4
-2, 5
1, -4
1, 5
3, 5

Two Sum Problem with HashSet not working with duplicates

I am working on an assignment where I have to find pairs of numbers summing up to "x" with average/best O(n) or linear runtime complexity. I can not use brute force as it will increase the complexity.
I am using HashSet and using contains method I am checking If I can find (x - array[i]) and printing it. But contains method checks for the whole HashSet where I want to start that search after "i"th position at each iteration. Also, I can not sort them as I have to print them in an order they appear in the input array.
if (hSet.Contains(x - array[i]))
{
Console.Write("(" + array[i] + "," + (x - array[i]) + ")");
hSet.Add(array[i]);
}
}
With Input array { 1, 6, 3, 2, 5, 5, 7, 8, 4, 8, 2, 5, 9, 9, 1 };
My Output (1,9)(6,4)(3,7)(2,8)(5,5)(5,5)(7,3)(8,2)(4,6)(8,2)(2,8)(5,5)(9,1)(9,1)
Expected output: (1,9), (1,9), (6,4), (3,7), (2,8), (2,8), (5,5), (5,5), (5,5), (8,2), (8,2), (9,1), (9,1)
This code work as your expectation with O(n) complexity (in most of case). Using a Dictionary, not a HashSet.
First, build the dictionary from array with the key is the item, the value is the count of the item.
After that, iterate over items, check it with the dictionary and produce the output. Also reduce the count of this item in the Dictionary to avoid unnecessary output later.
Here is the code:
using System;
using System.Collections.Generic;
class MainClass {
public static void Main (string[] args) {
int[] array = { 1, 6, 3, 2, 5, 5, 7, 8, 4, 8, 2, 5, 9, 9, 1 };
int x = 10;
// build dictionary
Dictionary<int,int> dict = new Dictionary<int,int>();
for(int i=0; i< array.Length; i+=1){
if(dict.ContainsKey(array[i])){
dict[array[i]] += 1;
} else {
dict.Add(array[i], 1);
}
}
// using dictionary
for(int i=0; i< array.Length; i+=1){
if(dict.ContainsKey(x - array[i])) {
int count = dict[x - array[i]];
if(x - array[i] == array[i]){
count -= 1;
}
for(int j = 0; j< count; j+=1 ) {
Console.Write("(" + array[i] + "," + (x - array[i]) + ")");
}
dict[array[i]] -=1;
if(dict[array[i]] == 0){
dict.Remove(array[i]);
}
}
}
Console.WriteLine();
}
}
Here is my easy solution using Dictionary. O(n) time.
namespace TwoSumLeetCode
{
class Program
{
static void Main(string[] args)
{
int[] arr = { 1, 2, 7, 9, 4 };
int target = 13;
Console.WriteLine(TwoSum(arr, target));
Console.ReadLine();
}
// assuming array and target are provided.
public static int[] TwoSum(int[] nums, int target)
{
Dictionary<int, int> dict = new Dictionary<int, int>();
for (int i = 0; i < nums.Length(); ++i)
{
if (dict.ContainsKey(target - nums[i]))
{
return new int[] { dict[target - nums[i]], i };
}
else
{
dict[nums[i]] = i;
}
}
return null;
}
}
}

How to find the longest sequence of equal elements in an array of integers?

I want to write a program that finds the longest sequence of equal elements in an array of integers. If several longest sequences exist, we should print the leftmost one. e.g. Input: 0 1 1 5 2 2 6 3 3
Output: 1 1
I know that my code doesn't work correctly, but I don't know how to fix it. I should solve the problem using only arrays because I don't know how to use lists.
int[] numbers = Console.ReadLine().Split().Select(int.Parse).ToArray();
for (int i = 0; i < numbers.Length; i++)
{
int[] currentSequenceOfEqualElements = new int[numbers.Length];
for (int j = i + 1; j < numbers.Length; j++)
{
if (numbers[i] == numbers[j])
{
if (currentSequenceOfEqualElements[0] == 0)
{
currentSequenceOfEqualElements[0] = numbers[i];
currentSequenceOfEqualElements[1] = numbers[i];
}
else
{
currentSequenceOfEqualElements[i + 2] = numbers[i];
}
}
else
{
break;
}
}
Console.WriteLine(string.Join(' ', currentSequenceOfEqualElements));
}
I will be very grateful if you can explain to me how to do it.
Here is the solution using the MoreLinq library (https://morelinq.github.io/) that mjwills suggested.
Once you get used to linq and morelinq methods the code is easier to understand than custom algo with nested loops and if.
var numbers = new int[]{ 0, 1, 1, 5, 2, 2, 6, 3, 3};
var result = numbers.GroupAdjacent(x => x)
.MaxBy(x => x.Count())
.FirstOrDefault();
foreach (var i in result)
{
Console.Write($"{i} ");
}
Here's a simple solution, using only loops and no linq. It should be nice and easy to understand.
int[] numbers = new[] { 0, 1, 1, 5, 2, 2, 6, 3, 3 };
// Some variables to keep track of the sequence we're currently looking
// at, and the longest sequence we've found so far. We're going to start
// the loop at the 2nd number, so we'll initialize these as if we've
// already processed the first number (which is 0, so we've seen the
// first number of a sequence of 0's).
// Number of numbers in the current sequence
int count = 1;
// Number which is part of the longest sequence so faar
int longestNum = numbers[0];
// Number of numbers in the longest sequence we've seen so far
int longestCount = 1;
for (int i = 1; i < numbers.Length; i++)
{
// We're starting a new sequence
if (numbers[i] != numbers[i-1])
{
count = 0;
}
count++;
// Have we just found a new longest sequence?
if (count > longestCount)
{
longestCount = count;
longestNum = numbers[i];
}
}
// longestNum = 1 and longestCount = 2 (because the longest sequence
// had 2 1's in it). Turn this into the string "1 1".
Console.WriteLine(
string.Join(" ", Enumerable.Repeat(longestNum, longestCount)));
// If you wanted to end up with an array containing [1, 1], then:
int[] result = new int[longestCount];
Array.Fill(result, longestNum);
I will illustrate a recursive answer for your question, below is the code, I kept some if-else statements that there is no need to have them, but at least the code shows the idea.
The code has a basic method that should be exposed as public and a private recursive method that does the heavy lifting. The longest sequence is the empty array(list)
var longSequenceEqualElem = new List<int>();
Later on the recursion, you pass all the elems of the array through all the recursion calls to keep querying the positions, the pos parameter indicates the position level of the recursion.
if (pos < elems.Length) //stop the recursion here, the position will fall out of the indexes of the array, just return what you have in sequence that should be the longest.
The following statement if (sequence.Contains(elems[pos])) means that you found the same number you were carrying on the sequence in the position pos, so you can add it to the sequence and call the recursion with the adjacent position(pos + 1)
If the element in position pos is not part of the sequence you had, then you need to call the recursion with a new sequence containing elems[pos] and later compare the result of that recursion call with the sequence you had to see which of them is the longest one.
Hope this helps
class Program
{
static void Main(string[] args)
{
var elemts = new int[] { 0, 1, 1, 5, 2, 2, 6, 3, 3 };
var result = LongestSequence(elemts);
foreach (var i in result)
{
Console.Write(i + "\t");
}
Console.ReadLine();
}
public static int[] LongestSequence(int[] elems)
{
var longSequenceEqualElem = new List<int>();
return LongestSequenceRec(elems, longSequenceEqualElem, 0);
}
private static int[] LongestSequenceRec(int[] elems, List<int> sequence, int pos)
{
if (pos < elems.Length)
{
if (sequence.Contains(elems[pos]))
{
sequence.Add(elems[pos]);
return LongestSequenceRec(elems, sequence, pos + 1);
}
else
{
var newSeq = LongestSequenceRec(elems, new List<int> { elems[pos] }, pos + 1);
return (newSeq.Length > sequence.Count) ? newSeq.ToArray() : sequence.ToArray();
}
}
return sequence.ToArray();
}
}
static void Main()
{
int[] array1 = new int[9] {0, 1, 1, 5, 2, 2, 6, 3, 3};
int[] array2 = new int[9] {0, 0, 0, 0, 0, 0, 0, 0, 0};
int max_count = 1;
int tempCount = 1;
int num = 0;
for (int i = 0; i < array1.Length - 1; i++)
{
if (array1[i] == array1[i + 1]) tempCount++;
else tempCount = 1;
if (tempCount > max_count)
{
max_count = tempCount;
num = array1[i];
}
}
for (int i = 0; i < max_count; i++) array2[i] = num;
for (int i = 0; i < max_count; i++) Console.Write(array2[i] + " ");
Console.ReadKey();
}

How to Convert int[] to int[,] - C#

I have an int array in one dimension:
var intArray=new[] { 1, 2, 3, 4, 5, 6 };
and I want to convert it to two dimensions, such as:
var intArray2D=new[,] { {1, 2}, {3, 4}, {5, 6} };
How do I achieve this with C#?
with a loop perhaps:
for (int i = 0; i < oldArr.Length; i=i+2)
{
newArr[i/2, 0] = oldArr[i];
newArr[i/2, 1] = oldArr[i + 1];
}
Untested, but should get you pointed in the right direction...
If the one dimensional array contains the primitive data in row major order, and the total capacity of the 2 dimensional array equals the length of the one dimensional array, you can use this.
int[] source = new int[6];
int[,] target = new int[3, 2];
Buffer.BlockCopy(source, 0, target, 0, source.Length * sizeof(int));
Note that unlike Array.Copy and other array/list methods, Buffer.BlockCopy operates on a number of bytes of data, even if each element of the array is larger than 1 byte. It also only operates on arrays of primitive data types.
Additional references:
Multi-dimensional arrays are stored in row-major order (ECMA-335 Partition I, ยง8.9.1)
Buffer.BlockCopy
Edit: Here is a complete unit test.
[TestMethod]
public void SOTest16203210()
{
int[] source = new int[6] { 1, 2, 3, 4, 5, 6 };
int[,] destination = new int[3, 2];
Buffer.BlockCopy(source, 0, destination, 0, source.Length * sizeof(int));
Assert.AreEqual(destination[0, 0], 1);
Assert.AreEqual(destination[0, 1], 2);
Assert.AreEqual(destination[1, 0], 3);
Assert.AreEqual(destination[1, 1], 4);
Assert.AreEqual(destination[2, 0], 5);
Assert.AreEqual(destination[2, 1], 6);
}
I believe you want to split an integer array into an array of two integers each:
int[] list = new int[] { 1, 2, 3, 4, 5, 6};
int[][] newlist = new int[list.Length / 2][];
for (int i = 0, n = 0; i < list.Length; i += 2, n++)
{
newlist[n] = new[] { list[i], list[i + 1] };
}
To assign it to Points in particular you could try:
List<Point> plist = new List<Point>();
for (int i = 0; i < list.Length; i += 2)
{
plist.Add(new Point(list[i], list[i + 1]));
}
you may use this code. in here you can send any length you like. you can "deivde" the arry[] to arry[,] for any lenth.2 or 3 or what ever you like! as long as size % a.length ==0 !!!!
code
static int[,] convert(int[] a, int size)
{
int[,] value = new int[a.Length / size, size];
int counter = 0;
//
for (int b = 0; b < value.GetLength(0); b++)
for (int c = 0; c < value.GetLength(1); c++)
{
value[b, c] = a[counter];
counter++;
}
return value;
}
If the product of the dimensions are the same, the fastest way would probably be to pin the matrix using a fixed statement, then to use the Marshalling class to copy the continuous block from the array to an IntPtr created from the void* you got from the fixed.
You would have to wrap this in an unsafe statement and enable unsafe in the assembly's build config.
I have converted this from vb to c#
int Size = OldArray.Length;
int[,] NewPoints = null;
if (Size % 2 != 0) {
//Error - Array has odd number of elements!
} else {
for (i = 0; i <= Size - 1; i += 2) {
Array.Resize(ref AllPoints, (i / 2) + 1, 2);
NewPoints[i / 2, 0] = OldArray(i);
NewPoints[i / 2, 1] = OldArray(i + 1);
}
}
You could try this:
int [] a = {1,2,3,4,5,6};
int [,] b = new int[a.Length/2,2];
for(int i = 0;i<a.Length;i++)
{
b[i/2,i%2] = a[i];
}
Note that i/2 is an integer division, hence both 4/2 and 5/2 will give 2 which is a correct index in 2Darray for the tuple 5 and 6 from the original array. The second index is determined using reminder when divided by 2, it will give 0 if the index is even number and 1 if the index of the item from the original array is odd number.
I would consider this for any dimension of array:
public class TestClass {
public static void TestMethod2D() {
var intLinear=new[] { 1, 2, 3, 4, 5, 6 };
var indexer2D=new ArrayIndexer<int>(3, 2);
for(var i=intLinear.Length; i-->0; indexer2D[i]=intLinear[i])
;
var int2D=(int[,])indexer2D.ToArray();
}
public static void TestMethod4D() {
var intLinear=new[] { 1, 2, 3, 4, 5, 6 };
var indexer4D=new ArrayIndexer<int>(2, 2, 2, 2);
for(var i=intLinear.Length; i-->0; indexer4D[i]=intLinear[i])
;
var int4D=(int[, , ,])indexer4D.ToArray();
}
}
public partial class ArrayIndexer<T> {
public Array ToArray() {
return m_Array;
}
public ArrayIndexer(params int[] lengths) {
m_Array=Array.CreateInstance(typeof(T), lengths);
}
public T this[params int[] indices] {
set {
m_Array.SetValue(value, indices.Transform(m_Array));
}
get {
return (T)m_Array.GetValue(indices.Transform(m_Array));
}
}
Array m_Array;
}
public static partial class ArrayExtensions {
public static int[] Transform(
this int[] indices, Array array, bool isRowMajor=true) {
if(indices.Length>array.Rank)
return indices;
else {
var list=indices.ToList();
if(isRowMajor)
list.Reverse();
for(int r, q=0, i=0, count=array.Rank; count-->0; ++i) {
var index=isRowMajor?count-i:i;
if(indices.Length>i) {
q=Math.DivRem(indices[i]+q, array.GetLength(index), out r);
list[i]=r;
}
else {
if(index<0) {
list.Add(q);
q=0;
}
else {
q=Math.DivRem(q, array.GetLength(index), out r);
list.Add(r);
}
}
}
if(isRowMajor)
list.Reverse();
return list.ToArray();
}
}
}
ArrayExtensions.Transform is an indices transformer, it performs the linear transformation with the geometry of a given array. isRowMajor controls the layout, such as you would regard an int[,] in x, y or in y, x order.

Categories