var example = new[]{1, 1, 1, 0, 1, 1}
I want to produce an array of all arrays that have three 1s in combinations of places that this array does, and 0s in all other positions.
In this example, these will be:
1 1 1 0 0 0
1 1 0 0 1 0
1 1 0 0 0 1
1 0 1 0 1 0
1 0 1 0 0 1
1 0 0 0 1 1
0 1 1 0 1 0
0 1 1 0 0 1
0 1 0 0 1 1
0 0 1 0 1 1
Code I wrote to attempt this became extremely long and messy, there is obviously a better way.
I was trying using 'counters' that sat over positions of the original array, and moved like so:
1 1 1 0 1 1
c c c
c c c
c c c
c c c
etc...
If the array is relatively short (which it should be to avoid overflowing the memory) you could use binary counting to build and algorithm that you are looking for:
Assume that the original array has N elements
Convert the array to an int treating each position as a binary digit; call it set
Make a mask number that counts in a loop from 0 to (1 << N)-1, inclusive. This mask produces all possible combinations of bits that can be taken from the original
Produce a combination of mask and set by AND-ing the two: int candidate = mask & set
Check how many bits are set in the candidate
If the number of set bits is exactly three, add candidate to the list
Once the loop is finished, you have your list represented as ints.
Eliminate duplicates, and convert these ints to arrays of ints as necessary.
Here is a simple implementation of the above algorithm:
static uint FromArray(int[] data) {
uint res = 0;
for (int i = 0 ; i != data.Length ; i++) {
if (data[i] == 1) {
res |= (1U << i);
}
}
return res;
}
static int[] ToArray(uint set, int size) {
var res = new int[size];
for (int i = 0 ; i != size ; i++) {
if ((set & (1U << i)) != 0) {
res[i] = 1;
}
}
return res;
}
static int CountBits(uint set) {
int res = 0;
while (set != 0) {
if ((set & 1) != 0) {
res++;
}
set >>= 1;
}
return res;
}
public static void Main() {
var example = new[]{1, 1, 1, 0, 1, 1};
var set = FromArray(example);
int N = example.Length;
var res = new List<uint>();
for (uint mask = 0 ; mask != 1U<<N ; mask++) {
var candidate = set & mask;
if (CountBits(candidate) == 3) {
res.Add(candidate);
}
}
foreach (var s in res.Distinct()) {
var array = ToArray(s, N);
Console.WriteLine(string.Join(" ", array.Select(i => i.ToString()).ToArray()));
}
}
This code produces the following output:
1 1 1 0 0 0
1 1 0 0 1 0
1 0 1 0 1 0
0 1 1 0 1 0
1 1 0 0 0 1
1 0 1 0 0 1
0 1 1 0 0 1
1 0 0 0 1 1
0 1 0 0 1 1
0 0 1 0 1 1
Demo on ideone.
Related
I'm currently trying to print a ulong data type as 8x8 grid of binary bits since the ulong data type has 8 bytes - 64 bits. While trying to do so, I keep getting a bit turned on with 32-bit offset. To understand my problem, look at the following.
When I print the bits, I would like for it to be formatted this way.
8 | 0 0 0 0 0 0 0 0
7 | 0 0 0 0 0 0 0 0
6 | 0 0 0 0 0 0 0 0
5 | 0 0 0 0 0 0 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 0 0 0 0 0
2 | 0 0 0 0 0 0 0 0
1 | 0 0 0 0 0 0 0 0
- - - - - - - -
a b c d e f g h
Decimal: 0
Hexadecimal: 0
These are the two relevant methods used to print the bits in that way.
public static bool getBit(ulong board, int index) => (board & (1u << (index))) > 0;
public static void printBoard(ulong board)
{
for (int i = 7; i >= 0; i--)
{
Console.Write($"{i + 1} |");
for (int j = 0; j < 8; j++)
{
Console.Write(" {0}", getBit(board, (i * 8) + j) ? 1 : 0);
}
Console.WriteLine();
}
Console.WriteLine(" - - - - - - - -\n a b c d e f g h\n");
Console.WriteLine($" Decimal: {board}\n Hexadecimal: {board:X}\n");
}
Using these methods, when I run the program, I get this 8x8 grid for the following code.
ulong a = 0b10;
printBoard(a);
8 | 0 0 0 0 0 0 0 0
7 | 0 0 0 0 0 0 0 0
6 | 0 0 0 0 0 0 0 0
5 | 0 1 0 0 0 0 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 0 0 0 0 0
2 | 0 0 0 0 0 0 0 0
1 | 0 1 0 0 0 0 0 0
- - - - - - - -
a b c d e f g h
Decimal: 2
Hexadecimal: 2
Although decimal and hexadecimal formats indicate that I have 2 as the number stored in a, the 8x8 grid doesn't. Why is the bit on b5 or the 34th bit(counting from the bottom) turned on? When the 34th bit is turned on, the value of the variable a changes to a very high number in place of 2.
Is there something I need to understand about the underlying implementation of the ulong data type or is there something wrong with what I'm doing?
Any advice or suggestion is appreciated.
You'll find the answer here: what is 1u?
The answer is an int32 and not an int64 as you expected.
You just have to replace 1u by 1ul in your getBit method.
I am not sure if I am in the correct area on stack - so my apologies first ..
I need to know how I can calculate all possible combinations (for 3 different fixed lengths) that can fit into a Rod of n length.
So for example if I have 3 fixed lengths of 8, 10, 12 and a Rod of variable Length n say 50'; I want to know all the possible cuts that I can make.
Using Microsoft Solver Foundation:
const int rodLength = 50;
const int lengthA = 8, lengthB = 10, lengthC = 12;
var solver = SolverContext.GetContext();
var model = solver.CreateModel();
var decisionA = new Decision(Domain.IntegerNonnegative, "A");
model.AddDecision(decisionA);
var decisionB = new Decision(Domain.IntegerNonnegative, "B");
model.AddDecision(decisionB);
var decisionC = new Decision(Domain.IntegerNonnegative, "C");
model.AddDecision(decisionC);
model.AddGoal("Goal", GoalKind.Minimize,
rodLength - (decisionA * lengthA) - (decisionB * lengthB) - (decisionC * lengthC));
int maxItems = (rodLength / new [] { lengthA, lengthB, lengthC }.Min());
model.AddConstraint("MaxItems", decisionA + decisionB + decisionC < maxItems);
var solution = solver.Solve();
Console.WriteLine("A " + decisionA.GetDouble());
Console.WriteLine("B " + decisionB.GetDouble());
Console.WriteLine("C " + decisionC.GetDouble());
where we trying to minimize the difference between the rod length and the sum of the items constraining the number of items (in your case max 50 / 8 = 6 items).
Here is sample of code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication104
{
class Program
{
static void Main(string[] args)
{
string max = "111111";
int size = 50;
List<List<int>> numbers = CountModThree(max,size);
Print(numbers);
Console.ReadLine();
}
static List<List<int>> CountModThree(string max,int size)
{
List<List<int>> results = new List<List<int>>();
List<int> newMod3 = new List<int>() {0};
while(true)
{
int length = newMod3.Select(x => x == 0 ? 8 : x == 1 ? 10 : 12).Sum();
if (length <= size) results.Add(newMod3);
if (string.Join("", newMod3) == max) break;
newMod3 = AddOne(newMod3);
}
return results;
}
static List<int> AddOne(List<int> number)
{
List<int> newNumber = new List<int>();
newNumber.AddRange(number);
int carry = 1;
for (int i = number.Count - 1; i >= 0; i--)
{
int digit = newNumber[i] + carry;
if (digit == 3)
{
newNumber[i] = 0;
carry = 1;
}
else
{
newNumber[i] = digit;
carry = 0;
break;
}
}
if (carry == 1) newNumber.Insert(0, 0);
return newNumber;
}
static void Print(List<List<int>> numbers)
{
foreach(List<int> number in numbers)
{
Console.WriteLine("string : '{0}', Total Length : '{1}, Number 8ft sections : '{2}', Number 10ft sections : '{3}', Number 12ft sections : '{4}'",
string.Join("", number),
number.Select(x => x == 0 ? 8 : x == 1 ? 10 : 12).Sum(),
number.Where(x => x == 0).Count(),
number.Where(x => x == 1).Count(),
number.Where(x => x == 2).Count()
);
}
}
}
}
You want to get all partitions of n into predefined integer pieces. Simple approach is using recursion.
Python code gives all possible solutions, ignoring summands order due to last index usage. So 8 8 8 8 8 10 and 8 8 10 8 8 8 variants are considered the same. If you need to distinguish them, just remove last argument and start loop from 0.
def solution(sum, lst, last, sol):
if sum == 0:
print(sol)
return
for i in range(last, len(lst)):
if lst[i] <= sum:
solution(sum - lst[i], lst, i, sol + " " + str(lst[i]))
return
solution(50, [8,10,12], 0, "")
8 8 8 8 8 10
8 8 10 12 12
8 10 10 10 12
10 10 10 10 10
If you need also solutions with smaller overall length (if n is unreachable) - remember solutions with small rest of sum, then use ones with the smallest rest. Quick-made example:
dict = [[] for i in range(10)]
def solution(sum, lst, last, sol):
if sum == 0:
print(sol)
return
if sum < 10:
dict[sum].append(sol)
for i in range(last, len(lst)):
if lst[i] <= sum:
solution(sum - lst[i], lst, i, sol + " " + str(lst[i]))
return
solution(50, [5, 13 , 21], 0, "")
for i in range(1, len(dict)):
if len(dict[i]) > 0:
print(dict[i])
break
5 5 5 5 5 5 5 5 5 5 #exact
[' 5 5 5 13 21', ' 5 5 13 13 13'] #inexact but close
There is also non-recursive method: make table A[0..n] and fill it with items (note that table might be huge!)
def tablecuts(sum, lst):
cuts = [[] for i in range(sum+1)]
cuts[0].append('*')
for item in lst:
for i in range(0, sum - item + 1):
if len(cuts[i]) > 0:
for j in cuts[i]:
cuts[i+item].append(j+" " + str(item))
for i in range(len(cuts)):
print(i, cuts[i])
tablecuts(13, [2,5,7])
0 ['*']
1 []
2 ['* 2']
3 []
4 ['* 2 2']
5 ['* 5']
6 ['* 2 2 2']
7 ['* 2 5', '* 7']
8 ['* 2 2 2 2']
9 ['* 2 2 5', '* 2 7']
10 ['* 2 2 2 2 2', '* 5 5']
11 ['* 2 2 2 5', '* 2 2 7']
12 ['* 2 2 2 2 2 2', '* 2 5 5', '* 5 7']
13 ['* 2 2 2 2 5', '* 2 2 2 7']
How to concat a number of arrays as a single array in C#?
using System;
using System.Linq;
namespace Exp2
{
class Program2
{
static void Main(string[] args)
{
Program2 pgm = new Program2();
Console.Write("Enter number of Arrays do you want : ");
int numberOfArrays = int.Parse(Console.ReadLine());
int[] narray = new int[numberOfArrays];
int[] el=new int[100];
int[] el1 = new int[100];
for (int i = 0; i < narray.Length; i++)
{
Console.Write("Enter number of Elements do you want in Array {0}: ",i+1);
int ai = int.Parse(Console.ReadLine());
for (int j = 0; j < ai; j++)
{
Console.Write("Enter the {1} Elements do you want in Array {0}: ", i+1,j+1);
el[j]= int.Parse(Console.ReadLine());
}
el1 =el1.Concat(el).ToArray();
}
foreach (int val in el1)
{
Console.Write(val+" ");
}
Console.ReadLine();
}
}
}
Input:
Enter number of Arrays do you want : 3
Enter number of Elements do you want in Array 1: 3
Enter the 1 Elements do you want in Array 1: 5
Enter the 2 Elements do you want in Array 1: 6
Enter the 3 Elements do you want in Array 1: 9
Enter number of Elements do you want in Array 2: 4
Enter the 1 Elements do you want in Array 2: 5
Enter the 2 Elements do you want in Array 2: 8
Enter the 3 Elements do you want in Array 2: 2
Enter the 4 Elements do you want in Array 2: 2
Enter number of Elements do you want in Array 3: 5
Enter the 1 Elements do you want in Array 3: 32
Enter the 2 Elements do you want in Array 3: 4
Enter the 3 Elements do you want in Array 3: 6
Enter the 4 Elements do you want in Array 3: 6
Enter the 5 Elements do you want in Array 3: 4
Output:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 6 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 8 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 4 6 6 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
How can I display only the input of user?
If you don't know the number of elements, you can use List rather than array.
Concat is easy in list.
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
// Do your action to assign elements in list1 and list2
// To add list1 into list2
list2.AddRange(list1);
You can use a dictionary and a List :
The dictionary maps the list to its number.
var dict = new Dictionary<int, List<int>>();
Console.WriteLine("Enter number of Arrays do you want : ");
int numberOfArrays = int.Parse(Console.ReadLine());
for(int k = 1; k < numberOfArrays; k++)
{
var currentArray = dict[k] = new List<int>();
Console.WriteLine($"Enter array {k} Length:");
int arrayLength = int.Parse(Console.ReadLine());
for (int j = 0; j < arrayLength; j++)
{
Console.WriteLine($"Enter the {j}-th Element you want in Array {k}: ");
currentArray.Add(int.Parse(Console.ReadLine()));
}
}
foreach(var pair in dict)
{
Console.WriteLine($"{pair.Key}-th array elements : ");
foreach(var element in pair.Value)
{
Console.WriteLine(element);
}
}
It Work now,
using System;
using System.Collections.Generic;
using System.Linq;
namespace Exp2
{
class Program2
{
static void Main(string[] args)
{
Program2 pgm = new Program2();
Console.Write("Enter number of Arrays do you want : ");
int numberOfArrays = int.Parse(Console.ReadLine());
int[] narray = new int[numberOfArrays];
int[] el=new int[100];
int[] el1 = new int[100];
List<int> list1 = new List<int>(100);
List<int> list2 = new List<int>(100);
for (int i = 0; i < narray.Length; i++)
{
Console.Write("Enter number of Elements do you want in Array {0}: ",i+1);
int ai = int.Parse(Console.ReadLine());
for (int j = 0; j < ai; j++)
{
Console.Write("Enter the {1} Elements do you want in Array {0}: ", i+1,j+1);
//list1[j]= int.Parse(Console.ReadLine());
int kj = int.Parse(Console.ReadLine());
list1.Add(kj);
}
//el1 =el1.Concat(el).ToArray();
list2.AddRange(list1);
}
foreach (int val in list2)
{
Console.Write(val+" ");
}
Console.ReadLine();
}
}
}
Thank you all..!
Don't use "foreach" loop use "for" loop like this .
for (int i= 0;i< el1.Length;i++)
{
if (el1[i] != 0)
Console.Write(el1[i] + " ");
else continue;
}
warning: In some input cases you might get extra number as last element of output
So I am a beginner and I am building a C# Crozzle game.I am trying to find space in a two dimensional array that could possible store a word. So for example, I have a two dimensional array like this:
[ 0 1 1 0 0 0 0 ]
[ 0 1 1 0 1 1 1 ]
[ 0 1 1 0 1 1 1 ]
[ 0 1 1 0 1 1 1 ]
[ 0 1 1 0 1 1 1 ]
0 represents the cell being empty, and 1 represents that it contains a value. I want to get a collection of coordinates that are free.
So eventually I want to store the starting and end coordinate, like:
[0,0] -> [0,4],
[3,0] -> [3,4],
[3,0] -> [6,0]
Storing them isn't the issue, the issue is finding these patterns of 0's. Anyone know the best way of working this out?
Thanks!
You have to scan lines and columns of the 2D array. To show up the idea, I've chosen
Tuple<int, int>
Tuple<Point, Point>
to represent ranges in the 1D and 2D arrays correspondingly. Sure, that Tuple<Point, Point> is not a good choice and you, probably, want to change it for some tailored class.
private static IEnumerable<Tuple<int, int>> ScanLine<T>(IEnumerable<T> source, T sample, int atLeast) {
int count = 0;
int index = -1;
foreach (var item in source) {
index += 1;
if (Object.Equals(item, sample))
count += 1;
else {
if (count >= atLeast)
yield return new Tuple<int, int>(index - count, index - 1);
count = 0;
}
}
if (count >= atLeast)
yield return new Tuple<int, int>(index - count + 1, index);
}
private static IEnumerable<Tuple<Point, Point>> ScanBoard<T>(T[,] source, T sample, int atLeast) {
// Lines scan
for (int i = 0; i < source.GetLength(0); ++i) {
var line = Enumerable.Range(0, source.GetLength(1)).Select(c => source[i, c]);
foreach (var item in ScanLine(line, sample, atLeast))
yield return new Tuple<Point, Point>(new Point(item.Item1, i), new Point(item.Item2, i));
}
// Columns scan
for (int i = 0; i < source.GetLength(1); ++i) {
var line = Enumerable.Range(0, source.GetLength(0)).Select(r => source[r, i]);
foreach (var item in ScanLine(line, sample, atLeast))
yield return new Tuple<Point, Point>(new Point(i, item.Item1), new Point(i, item.Item2));
}
}
Test
int[,] board = new int[,] {
{ 0, 1, 1, 0, 0, 0, 0 },
{ 0, 1, 1, 0, 1, 1, 1 },
{ 0, 1, 1, 0, 1, 1, 1 },
{ 0, 1, 1, 0, 1, 1, 1 },
{ 0, 1, 1, 0, 1, 1, 1 },
};
// room for 3-letter words
Console.Write(String.Join(Environment.NewLine, ScanBoard(board, 0, 3)));
Returns
({X=3,Y=0}, {X=6,Y=0})
({X=0,Y=0}, {X=0,Y=4})
({X=3,Y=0}, {X=3,Y=4})
For example, it is not possible to remove 0 or 1 characters from "aaabbbcc" to make an equal number of each character, but it is for "aaabbcc" (remove 1 'a').
My algorithm is passing 12/15 test cases and the ones it isn't passing have too large of input to possible debug. My guess is that there's some corner case I'm missing in my algorithm. Let me know if you see any flaws in the logic which I've detailed in comments.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution
{
static void Main(String[] args)
{
string s = Console.ReadLine();
// s = source string, consists of characters in range 'a', ..., 'z'
int[] f = Enumerable.Repeat(0, 26).ToArray();
foreach(var c in s)
f[c - 'a'] += 1;
// f[0] = # of 'a' characters, ..., f[25] = # of 'z' characters
var ff = new Dictionary<int,int>();
foreach(var k in f.Where(x => x > 0)) // for non-zero character frequencies
{
// run an "add or increment" on the frequencies of character frequencies
if(ff.ContainsKey(k)) ff[k] += 1;
else ff[k] = 1;
if(ff.Keys.Count() > 2)
{
// if there are more than 2 distinct counts of characters, it is impossible to level
// the counts by removing a single character
Console.WriteLine("NO");
return;
}
}
// ff[k] = frequency of the count k of a character in s, excluding any non-zero counts
var ffl = ff.ToList();
if(ffl.Count == 2)
{
// If there are 2 distinct frequencies of characters, one of those frequencies must be
// represented only 1 time and its frequecy must be 1 more than other one.
// For example, if s="aaabbcc" then ffl = { {3,1}, {2,2} }, meaning that there is 1 example
// of a character that appears 3 times (the 'a') and 2 examples of characters that appear 2
// times (the 'b' and 'c'). So we can remove 1 'a' to level the character counts.
// For another example, if s="aaabbbcc", then ffl = { {3,2}, {2,1} }, meaning that there are 2
// examples of a character appearing 3 times (the 'a' and 'b') and 1 example of a
// character appearing 2 times (the 'c'). So we have no way of leveling the character counts.
KeyValuePair<int,int> oneff, other;
if(ffl[0].Value == 1)
{
oneff = ffl[0];
other = ffl[1];
}
else if(ffl[1].Value == 1)
{
oneff = ffl[1];
other = ffl[0];
}
else
{
Console.WriteLine("NO");
return;
}
if((oneff.Key - 1) != other.Key)
{
Console.WriteLine("NO");
return;
}
}
// if we're here, there are 1 or fewer distinct counts of characters, meaning the
// frequency of characters in the string is already level
Console.WriteLine("YES");
}
}
EDIT: I found the corner case on my own. If the frequency that is represented 1 time is 1, then we're good. For example, with
a -> 111
b -> 111
c -> 111
d -> 111
e -> 111
f -> 111
g -> 111
h -> 111
i -> 111
j -> 0
k -> 0
l -> 0
m -> 0
n -> 1
o -> 0
p -> 0
q -> 0
r -> 0
s -> 0
t -> 0
u -> 0
v -> 0
w -> 0
x -> 0
y -> 0
z -> 0
we can remove the n character. I changed
if((oneff.Key - 1) != other.Key)
to
if((oneff.Key != 1) && (oneff.Key - 1) != other.Key)
and it worked.