Convert binary number 5 into list of intergers (4,1) - c#

I have a configuration value expressed as a binary number to allow several options within the same value.
E.g. the value of 5 would be "101" or both 4 and 1.
Does anyone know of the best/fastest way to "input" the value '5' and get a list of {1,4} back?

If you want to get powers of 2 which the value consists of:
int value = 5;
var addendums = Enumerable.Range(0, sizeof(int) * 8 - 1)
.Select(i => (1 << i) & value)
.Where(x => x != 0)
.ToList();
Result:
[ 1, 4 ]
Note that if you want to have addendums in descending order, you can apply Reverse() after filtering sequence.
TL;DR The first step generates integer values which correspond to bit positions in integer value 0, 1, 2, ..., 31. Max index is a number of bits in Int32 value - 1 (because we need the index of the bit).
Next step selects a result of bitwise AND operation of the 1 shifted to the corresponding index (same as the power of 2) with the value itself (only first 4 bits shown here):
i 1<<i value (1<<i) & value
Binary Binary Binary Decimal
0 0001 0101 0001 1
1 0010 0101 0000 0
2 0100 0101 0100 4
3 1000 0101 0000 0
...
All you have to do after this step - filter out zeroes.

Some bit shifting and & later...
int n = 5+32;
var lst = new List<int>();
int i = 1;
while (n > 0)
{
if ((n & i) == i)
{
lst.Add(i);
n &= ~i;
}
i <<= 1; // equivalent to i *= 2
}
A little more esoteric, with the use of xor (^):
if (n != 0)
{
while (true)
{
if ((n & i) != 0)
{
lst.Add(i);
n ^= i;
if (n == 0)
{
break;
}
}
i <<= 1; // equivalent to i *= 2
}
}

I have made this little sample. Here you obtain from an integer its value as a sum of its powers of two. Thosw powers should be your input options
class Program
{
static void Main(string[] args)
{
var input = 5;
var options = new List<uint>();
for (uint currentPow = 1; currentPow != 0; currentPow <<= 1)
if ((currentPow & input) != 0)
options.Add(currentPow);
foreach (var option in options)
Console.WriteLine(option);
Console.ReadLine();
}
}
And the output is: 1 4
EDIT>>> In fact this does the same as #Sergey Berezovskiy answer but without LINQ
Hope it helps

The naive approach:
int originalInput = 42;
int input = originalInput;
// Generate binary numbers
var binaryNumbers = Enumerable.Range(0, 31).Select(n => (int)Math.Pow(2, n)).ToArray();
// Largest first
Array.Reverse(binaryNumbers);
var result = new List<int>();
foreach (var bin in binaryNumbers)
{
if (input >= bin)
{
result.Add(bin);
input -= bin;
}
}
Console.WriteLine($"{originalInput} decomposed: " + string.Join(" ", result));
Generate a range of power-of-two numbers, ranging from 2^31 (1073741824) to 2^0 (1), then check whether the input is equal to or larger than those numbers, and if so, add that number to the result list and subtract it from the input.
Now that that's all written out, see how Sergey's answer greatly reduces the code required by some Linq and bitshifting magic.
A hybrid solution, inspired by combining both answers:
var input = 42;
var output = Enumerable.Range(0, 31)
.Select(n => (int)Math.Pow(2, n))
.Where(p => (p & input) > 0);
Console.WriteLine($"{input} decomposed: " + string.Join(" ", output));

A maybe more traditional and easy to understand solution. You convert the number into a string binary representation, and then analyze each character to extract the corresponding decimal representations of each bit at 1.
int number = 5;
string binaryRep = Convert.ToString(number, 2);
List<int> myList = new List<int>();
int pow = 0;
for(int i = binaryRep.Count() - 1; i >= 0; i--)
{
if(binaryRep[i] == '1')
{
myList.Add((int)Math.Pow(2, pow));
}
pow++;
}

Short and fast:
int input = 5;
var list = new List<int>();
for (int i = 1, j = input; i <= j; i *= 2, input >>= 1){
if ((input & 1) == 1)
list.Add(i);
}

To show binary representation use
int value = 7;
var binary = Convert.ToString(value, 2);
To see binary numbers:
private int[] ToBinaryNumbers(int value)
{
var binary = Convert.ToString(value, 2).Reverse();
int ix = 0;
return binary.Select(x => { var res = x == '1' ? (int?)Math.Pow(2, ix) : (int?)null; ix++; return res; }).Where(x => x.HasValue).Select(x => x.Value).ToArray();
}
This will give you 1,2,4 for 7 or 1,8 for 9

Related

Algorithm converting lotto ticket number to integer value and back again

I'm looking for the algorithm to convert a lotto ticket number to an integer value an back again.
Let's say the lotto number can be between 1 and 45 and a tickets contains 6 unique numbers. This means there are a maximum of 8145060 unique lotto tickets.
eg:
01-02-03-04-05-06 = 1
01-02-03-04-05-07 = 2
.
.
.
39-41-42-43-44-45 = 8145059
40-41-42-43-44-45 = 8145060
I'd like to have a function (C# preferable but any language will do) which converts between a lotto ticket and an integer and back again. At the moment I use the quick and dirty method of pre-calculating everything, which needs a lot of memory.
For enumerating integer combinations, you need to use the combinatorial number system. Here's a basic implementation in C#:
using System;
using System.Numerics;
using System.Collections.Generic;
public class CombinatorialNumberSystem
{
// Helper functions for calculating values of (n choose k).
// These are not optimally coded!
// ----------------------------------------------------------------------
protected static BigInteger factorial(int n) {
BigInteger f = 1;
while (n > 1) f *= n--;
return f;
}
protected static int binomial(int n, int k) {
if (k > n) return 0;
return (int)(factorial(n) / (factorial(k) * factorial(n-k)));
}
// In the combinatorial number system, a combination {c_1, c_2, ..., c_k}
// corresponds to the integer value obtained by adding (c_1 choose 1) +
// (c_2 choose 2) + ... + (c_k choose k)
// NOTE: combination values are assumed to start from zero, so
// a combination like {1, 2, 3, 4, 5} will give a non-zero result
// ----------------------------------------------------------------------
public static int combination_2_index(int[] combo) {
int ix = 0, i = 1;
Array.Sort(combo);
foreach (int c in combo) {
if (c > 0) ix += binomial(c, i);
i++;
}
return ix;
}
// The reverse of this process is a bit fiddly. See Wikipedia for an
// explanation: https://en.wikipedia.org/wiki/Combinatorial_number_system
// ----------------------------------------------------------------------
public static int[] index_2_combination(int ix, int k) {
List<int> combo_list = new List<int>();
while (k >= 1) {
int n = k - 1;
if (ix == 0) {
combo_list.Add(n);
k--;
continue;
}
int b = 0;
while (true) {
// (Using a linear search here, but a binary search with
// precomputed binomial values would be faster)
int b0 = b;
b = binomial(n, k);
if (b > ix || ix == 0) {
ix -= b0;
combo_list.Add(n-1);
break;
}
n++;
}
k--;
}
int[] combo = combo_list.ToArray();
Array.Sort(combo);
return combo;
}
}
The calculations are simpler if you work with combinations of integers that start from zero, so for example:
00-01-02-03-04-05 = 0
00-01-02-03-04-06 = 1
.
.
.
38-40-41-42-43-44 = 8145058
39-40-41-42-43-44 = 8145059
You can play around with this code at ideone if you like.
there seem to be actually 45^6 distinct numbers, a simple way is to treat the ticket number as a base-45 number and convert it to base 10:
static ulong toDec(string input){
ulong output = 0;
var lst = input.Split('-').ToList();
for (int ix =0; ix< lst.Count; ix++)
{
output = output + ( (ulong.Parse(lst[ix])-1) *(ulong) Math.Pow(45 , 5-ix));
}
return output;
}
examples:
01-01-01-01-01-01 => 0
01-01-01-01-01-02 => 1
01-01-01-01-02-01 => 45
45-45-45-45-45-45 => 8303765624

How to encode a decimal number to binary in 16 bits in C#?

The problem is asking :
The user gives me integer n,
I convert it to binary in 16 bits,
inverse the binary,
then decode the inverse binary into a new integer.
example:
14769 is 0011100110110001 (the 2 zeros in the front are the problem for me)
inverse the binary:
1000110110011100
Decode:
36252
I wrote the code but when I convert to binary it only gives me
11100110110001 without 00 in front, so the whole inverse binary will change and the new integer will be different.
This is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace HelloWorld
{
public class Program
{
public static void Main(string[] args)
{
long n, n1, p, i, r, sum, inv, inv1, newint;
Console.WriteLine("give n:");
n=long.Parse(Console.ReadLine());
n1=n;
p=1;
sum=0;
i=n;
//for below is for the binary representation of n
for(i=n;i!=0;i=i/2)
{
r=i%2;
sum=sum+r*p;
p=p*10;
}
inv=0;
//for below is to inverse the above binary representation
for(i=sum;i!=0;i=i/10)
{
r=i%10;
inv=10*inv+r;
}
inv1=inv;
newint=0;
p=0;
//for below is to decode the inverse binary to its decimal representation
for(i=inv;i!=0;i=i/10)
{
r=i%10;
newint=newint+r*(long)Math.Pow(2,p);
p=p+1;
}
Console.WriteLine("The number that you gave = {0} \nIts binary
representation = {1} \n\nThe inverse binary representation = {2} \nThe integer corresponding to the inverse binary number = {3}", n1, sum, inv1, newint);
}
}
}
So how can i encode on 16 bits?
Edit:
1)We didn't learn built in functions
2)We didn't learn padding or
Convert.Int...
3)We only know the for loop (+ while loop but better not use it)
4)We can't use strings either
You could reverse the bits using some simple bitwise operators.
ushort num = 14769;
ushort result = 0;
// ushort is 16 bits, therefore exactly 16 iterations is required
for (var i = 0; i < 16; i++, num >>= 1){
// shift result bits left by 1 position
result <<= 1;
// add the i'th bit in the first position
result |= (ushort)(num & 1);
}
Console.WriteLine(result); //36252
You can try using Convert to obtain binary representation and Aggregate (Linq) to get back decimal:
using System.Linq;
...
int value = 14769;
int result = Convert
.ToString(value, 2) // Binary representation
.PadLeft(16, '0') // Ensure it is 16 characters long
.Reverse() // Reverse
.Aggregate(0, (s, a) => s * 2 + a - '0'); // Back to decimal
Console.Write($"{value} => {result}");
Output:
14769 => 36252
Edit: Loop solution (if you are not allowed to use the classes above...)
int value = 14769;
int result = 0;
for (int i = 0, v = value; i < 16; ++i, v /= 2)
result = result * 2 + v % 2;
Console.Write($"{value} => {result}");
Explanation (how for above works):
First of all how can we get all 16 bits of the number? We can use standard algorithm based on remainder:
14769 / 1 % 2 == 1,
14769 / 2 % 2 == 0,
14769 / 4 % 2 == 0,
14769 / 8 % 2 == 0,
14769 / 16 % 2 == 1,
...
these are the bits from right to left: 11100110110001. Typical code can be
int v = value; // we don't want to change value, let's work with its copy - v
for (int i = 0; i < 16; ++i) {
// rightmost bit
int bit = v % 2;
// we divide v by to to get rid of the rightmost bit
v = v / 2;
}
Note that we compute bits from right to left - in reverse order - the very order we are looking for! How can we build result from these bits?
result = bit0 + 2 * (bit1 + 2 * (bit2 + ...))))..)
So we can easily modify our loop into
int result = 0;
int v = value; // we don't want to change value, let's work with its copy - v
for (int i = 0; i < 16; ++i) {
// rightmost bit
int bit = v % 2;
result = result * 2 + bit;
// we divide v by to to get rid of the rightmost bit
v = v / 2;
}
Finally, if we get rid of bit and make v declared within loop we can get my loop solution

Algorithm to get which values make sum of a given number from array

I don't know to search or google it so I ask it here.
I have an array of integers with fixed size and exactly with this logic.
sample [1,2,4,8,16,32]
Now I am given a number for example 26. And I shall find the numbers whose sum will make this number, in this case is [2,8,16]
for a number of 20 it will be [4,16]
for 40 it is [8,32]
and for 63 it is all of these numbers [1,2,4,8,16,32]
What is the proper algorithm for that?
I know strictly that there is always this continuation that the number is double of the previous value.
as well as only the numbers from the given array will sum up to the given number and each number will be used only for once or none
If it will be in C# method that takes array of ints and an int value and returns the array of ints that contains the ints that sum up this number from the given array will be preferred.
Thank you
As you can see, the number are base-2, which means you can easily use shift.
You could try this:
private IEnumerable<int> FindBits(int value)
{
// check for bits.
for (int i = 0; i < 32; i++)
{
// shift 1 by i
var bitVal = 1 << i; // you could use (int)Math.Pow(2, i); instead
// check if the value contains that bit.
if ((value & bitVal) == bitVal)
// yep, it did.
yield return bitVal;
}
}
This method will check what bits are set and return them as an ienumerable. (which can be converted to an array of list)
Usage:
// find the bits.
var res = FindBits(40).ToArray();
// format it using the string.join
var str = $"[{string.Join(",", res)}]";
// present the results
Console.WriteLine(str);
Results in [8,32]
Extra info:
counter
00000001 = 1 = 1 << 0
00000010 = 2 = 1 << 1
00000100 = 4 = 1 << 2
00001000 = 8 = 1 << 3
00010000 = 16 = 1 << 4
00100000 = 32 = 1 << 5
01000000 = 64 = 1 << 6
10000000 = 128 = 1 << 7
Instead of writing all combinations you make a for loop which does the counter.
Some extra non-sense:
If you like lambda's, you could replace the FindBits with this:
private Func<int, IEnumerable<int>> FindBits = (int value) => Enumerable
.Range(0, 31)
.Select(i => 2 << i).Where(i => (value & i) == i);
But it's better to keep it simpel/readable.
First you should notice that
( 1 2 4 8 16 ... ) = (2^0 2^1 2^2 2^3 2^4 ... )
And that this is the same as finding a binary encoding for a decimal number. What you are looking for is an algorithm to transform a decimal or base 10 number to a binary or base 2 number.
The algorithm is pretty simple:
public List<int> dec_to_bin(int num)
{
List<int> return_list = new List<int>();
int index = 0;
int remainder = num;
int bit = 0;
while (remainder > 0)
{
bit = remainder % 2;
if (bit == 1 )
{
return_list.Add((int)Math.Pow(2, index));
}
remainder = remainder / 2;
index = index + 1;
}
return return_list;
}
There is a better way however that just uses the underlying encoding of the number which is already binary.
public List<int> dec_to_bin(int num)
{
List<int> return_list = new List<int>();
int value = 1;
while( value < num )
{
if( (value & num) == value )
{
return_list.Add(value);
}
value = value * 2;
}
return return_list;
}
Another way to state your requirement is "What are the unique powers of 2 that sum to a given integer?" Since computers work with powers of 2 natively, there are built-in goodies in most languages to do this very succinctly.
As a bonus, you can use existing .Net types and methods to eliminate the need to write your own loops.
Here's one approach:
IEnumerable<int> GetCompositePowersOf2(int input) =>
//convert to enumerable of bools, one for each bit in the
//input value (true=1, false=0)
new BitArray(new[] { input }).Cast<bool>()
// get power of 2 corresponding to the position in the enumerable
// for each true value, gets 0 for false values.
.Select((isOne, pos) => isOne ? (1 << pos) : 0)
//filter out the 0 values
.Where(pow => pow > 0);
I don't quite get the " takes array of ints " part, since this creation of sums only works with numbers that are the power of 2.
private int[] count (int num)
{
int factor = 0;
List<int> facts = new List<int>();
while (num > 0)
{
int counter = 0;
int div = num;
int remainder = 0;
while (remainder == 0)
{
remainder = div % 2;
div = div / 2;
counter++;
}
factor = 1;
for (int i = 1; i < counter; i++)
factor *= 2;
num = num - factor;
facts.Add(factor);
}
return (facts.ToArray());
}

Can somebody explains what happens in this algorithm to check if its a pandigital?

I know that the << operand shifts the left value of the operand with the value on the right with bits. So 1 << 2 would give 4. And the | operand copies a bit if it exists in either value. But I simply can't get my head around the code.
private static bool isPandigital(long n)
{
int digits = 0;
int count = 0;
int tmp;
while (n > 0)
{
tmp = digits;
digits = digits | 1 << (int)((n % 10) - 1);
if (tmp == digits)
{
return false;
}
count++;
n /= 10;
}
return digits == (1 << count) - 1;
}
Why does it say 1 << in line 8? And why is the module - 1?
On top of that I don't know what is happening on the last line when the value is returned. Help would be greatly apreciated. Thanks very much!
Doing
digits = digits | 1 << (int)((n % 10) - 1);
is the same thing as
long temp1 = n % 10; //Divide the number by 10 and get the remainder
long temp2 = temp1 - 1; //Subtract 1 from the remainder.
int temp3 = (int)temp2; //cast the subtracted value to int
int temp4 = 1 << temp3; //left shift 1 to the casted value. This is the same as saying "two to the power of the value of temp3"
int temp5 = digits | temp4; //bitwise or together the values of digits and that leftshifted number.
digits = temp5; //Assign the or'ed value back to digits.
The last line
return digits == (1 << count) - 1;
is just doing the same thing as
int temp1 = 1 << count; //left shift 1 `count` times, this is the same as saying "two to the power of the value of count"
int temp2 = temp1 - 1; //Subtract 1 from the leftshifted number.
bool temp3 = digits == temp2; //test to see if digits equals temp2
return temp3;
I don't know what "pandigital" means, but this break apart can help you understand what is happening.
If pandigital means "contains all possible digits for the given radix"
https://en.wikipedia.org/wiki/Pandigital_number
and the radix == 10, why not just check if the number contains all possible 0..9 digits:
private static bool isPandigital(long n) {
// I assume negative numbers cannot be pandigital;
// if they can, put n = Math.Abs(n);
if (n < 1023456789) // smallest pandigital
return false;
int[] digits = new int[10];
for (; n > 0; n /= 10)
digits[n % 10] += 1;
return digits.All(item => item > 0);
}
Edit: In case of bit array (each bit in digits represent a digit) implementation:
private static bool isPandigital(long n) {
// negative numbers can't be pandigital
if (n < 1023456789) // smallest pandigital
return false;
int digits = 0;
for (; n > 0; n /= 10)
digits |= (1 << (int)(n % 10));
// 0b1111111111
return digits == 1023;
}
I think the writer of the method attempted to do this:
static bool IsPandigital(long n) {
int digits = 0;
while (n > 0) {
//set the bit corresponding to the last digit of n to 1 (true)
digits |= 1 << (int)(n % 10);
//remove the last digit of n
n /= 10;
}
//digits must be equal to 1111111111 (in binary)
return digits == (1 << 10) - 1;
}
The << operator is not that difficult. You just have to think in binary.
1 << 0 is simply a 1 shifted zero places, so 1
1 << 1 is 10
1 << 2 is 100, etc
If you encounter a 2 and a 5 and you 'or' them together you will have 100100.
This means if you encounter all 10 digits, the end result will be ten 1's.
In the return statement, we check if digits equals ten 1's.
1 << 10 means a 10000000000. If you substract 1, you get 1111111111
All this in binary, of course.
He may have had a different definition of pandigital, or just a different requirement. If, for example zeroes are not allowed, you can simply change the last line to: digits == (1 << 10) - 2;

How can i find the number of 9s in an integer

I have the following method which should found the total number of 9 in an integer, the method is used to retrieve the employees' contract type based on the number of 9. i tried the below class:-
public class EmployeeCreditCards
{
public uint CardNumber(uint i)
{
byte[] toByte = BitConverter.GetBytes(i);
uint number = 0;
for (int n = 0; n < toByte.Length; n++)
{
if (toByte[i] == 9)
{
number = number + 1;
}
}
return number;
}
}
In which i am trying to find how many 9 are in the passed integer, but the above method will always return zero. Any idea what is going wrong?
You can do this simple with a little linq:
public int GetAmountOfNine(int i)
{
return i.ToString().Count(c => c.Equals('9'));
}
But do add using System.Linq; to the cs file.
Your answer isn't working because you are converting to bytes, converting the number to bytes does not generate a byte for each digit (via #Servy). Therefor if you would write every byte in your array to console/debug you wouldn't see your number back.
Example:
int number = 1337;
byte[] bytes = BitConverter.GetBytes(number);
foreach (var b in bytes)
{
Console.Write(b);
}
Console:
57500
You can however convert the int to a string and then check for every character in the string if it is a nine;
public int GetAmountOfNineWithOutLinq(int i)
{
var iStr = i.ToString();
var numberOfNines = 0;
foreach(var c in iStr)
{
if(c == '9') numberOfNines++;
}
return numberOfNines;
}
A classic solution is as follows: (Probably this is the fastest algorithm to find solution, it takes only O(log n) time.)
private int count9(int n)
{
int ret = 0;
if (n < 0)
n = -n;
while (n > 0)
{
if (n % 10 == 9) ++ret;
n /= 10; // divide the number by 10 (delete the most right digit)
}
return ret;
}
How does that work?
Consider an example, n = 9943
now ret = 0.
n % 10 = 3, which != 9
n = n / 10 = 994
n % 10 = 4 != 9
n = 99
n % 10 = 9, so ret = 1
n = 9
n % 10 = 9, so ret = 2
n = 0
Try
int numberOfNines = number.ToString().Where(c => c == '9').Count();
Since a string implements IEnumerable<char>, you can apply LINQ directly to the string without converting it to an enumeration of chars first.
UPDATE
Converting the uint to a byte array won't work the expected way, since the uint does not store the decimal digits of your number directly. The number is stored as a binary number that streches over four bytes. A unit has always four bytes, even if your number has 9 decimal digits.
You can convert the number to a string in order to get its decimal representation.

Categories