How can i solve this problem using bitwise operators? [duplicate] - c#

This question already has answers here:
Is there an simple way to swap the values of bits?
(4 answers)
Closed 1 year ago.
The problem is: Write a program that swaps the bits on positions {p, p+1,...,p+k-1} with bits on positions {q, q+1,...,q+k-1} of a given integer.
Honestly, I don't know what the answer should be and therefore I don't know if my solution is remotely valid, but I've tried solving it using a nested for loop.
Here is the code:
static void Main(string[] args)
{
int n = int.Parse(Console.ReadLine());
int p = int.Parse(Console.ReadLine());
int q = int.Parse(Console.ReadLine());
int k = int.Parse(Console.ReadLine());
for (int i = p; i < p + k - 1; i++)
{
for (int j = q; j < q + k - 1; j++)
{
int bitP = (n >> p) & 1;
int bitQ = (n >> q) & 1;
n = n & (~(1 << q)) | (p << q);
n = n & (~(1 << p)) | (q << p);
}
}
Console.WriteLine(n);
}

First, you only need one for loop.
Second, you need to use the loop index value.
See code below:
static void Main()
{
int n = int.Parse(Console.ReadLine());
int p = int.Parse(Console.ReadLine());
int q = int.Parse(Console.ReadLine());
int k = int.Parse(Console.ReadLine());
for (int i=0; i<k; i++)
{
// get binary value at index p+i
int valP = (n>>(p+i))&1;
// get binary value at index q+i
int valQ = (n>>(q+i))&1;
// if values are different, swap them
if(valP != valQ)
{
int maskP = (1<<(p+i));
int maskQ = (1<<(q+i));
n = n^(maskP|maskQ);
}
}
Console.WriteLine(n);
}
Let's put this in an image:
n=10010101
p=0
q=4
k=4
bit pos: 76543210
--------------------
i p+i q+i | 10010101
0 0 4 | x x // 1 and 1 : do nothing
| 10010101
1 1 5 | x x // 0 and 0 : do nothing
| 10010101
2 2 6 | x x // 1 and 0 : swap (xor with 01000100)
| 11010001
3 3 7 | x x // 0 and 1 : swap (xor with 10001000)
| 01011001
For code simplicity, I chose to move from least significant digit to most significant (i.e. right to left)
Other answer using the swap_bit proposed as answer here:
static int swap_bit(int n, int pos1, int pos2)
{
if ((n>>pos1)&1) != ((n>>pos2)&1)
n = n^((1<<pos1)|(1<<pos2));
return n;
}
static void Main()
{
int n = int.Parse(Console.ReadLine());
int p = int.Parse(Console.ReadLine());
int q = int.Parse(Console.ReadLine());
int k = int.Parse(Console.ReadLine());
for (int i=0; i<k; i++)
{
n = swap_bit(n, p+i, q+i);
}
Console.WriteLine(n);
}

Related

Codewar task. How to find simple square numbers by the condition?

I tried to solve this problem on Codewar, but I don`t understand how to find exceptions.
In this Kata, you will be given a number n (n > 0) and your task will be to return the smallest square number N (N > 0) such that n + N is also a perfect square. If there is no answer, return -1 (nil in Clojure, Nothing in Haskell).
Here code that I wrote:
using System;
public class SqNum
{
public static long solve(long n){
int N = 1;
long lTemp = n;
double sum, result;
bool isSqare;
while(true)
{
sum = lTemp + N;
result = Math.Sqrt(sum);
isSqare = result % 1 == 0;
if(n == 4)
{
return -1;
}
if(isSqare == true)
{
return Convert.ToInt32(result);
}
N++;
}
return -1;
}
}
If N (square) is p^2, and n+N=r^2, you can write
n + p^2 = r^2
n = r^2 - p^2
n = (r - p) * (r + p)
If we represent n as product of pair of divisors:
n = a * b // let a<=b
a * b = (r - p) * (r + p)
We have system
r - p = a
r + p = b
and
p = (b - a) / 2
When p is the smallest? In the case of maximal close factors b and a. So we can try to calculate divisors starting from square root of n. Also note that a and b should have the same parity (to make p integer)
Pseudocode:
int N = -1;
for (int a = Math.Ceiling(Math.Sqrt(n)) - 1; a > 0; a--) {
if (n % a == 0) {
int bma = n / a - a;
if (bma % 2 == 0) {
int p = bma / 2;
int N = p * p;
break;
}
}
}
Examples:
n = 16
first divisor below sqrt(16) a = 2, b=8
p = 3, 16 + 9 = 25
n = 13
first divisor below sqrt(13) a = 1, b=13
p = 6, 13 + 36 = 49
n = 72
first divisor below sqrt(72) is a = 8, b= 9 - but distinct parity!
so the next suitable pair is a = 6, b = 12
p = 3, 72 + 9 = 81

for-loop to cover range increasing/decreasing based on sign of step

How would I modify this for-loop so that it counts up for positive values of Step, but counts down for negative values of Step?
For Step = 2, the expected output is 2 4 6 8 10
For Step =- 2, the expected output is 10 8 6 4 2
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = 2;
for ( int i = Lower; i <= Upper; i += Step )
{
Console.Write(i + " ");
}
Just obey the KISS principle.
You can just put the logic into the initialiser and the condition of the for statement:
public static void ForLoopWithDirectionBasedOnStep(int minValue, int maxValue, int step)
{
// Avoid obvious hang
if ( step == 0 )
throw new ArgumentException("step cannot be zero");
// ( initialiser ; condition ; iterator )
for ( int i = step > 0 ? minValue : maxValue; minValue <= i && i <= maxValue; i += step )
Console.Write(i + " ");
}
so:
ForLoopWithDirectionBasedOnStep(minValue: 2, maxValue: 10, step: 2) returns:
2 4 6 8 10
ForLoopWithDirectionBasedOnStep(minValue: 2, maxValue: 10, step: -2) returns:
10 8 6 4 2
as desired.
The initialiser sets the start value
int i = step > 0 ? minValue : maxValue;
by using the conditional operator and is equivalent to
int i;
if ( step > 0 )
i = minValue;
else
i = maxValue;
The condition
minValue <= i && i <= maxValue
simply checks that the loop variable is within the range [minValue, maxValue].
Note that bad inputs are handled automatically because (emphasis mine):
The condition section, if present, must be a boolean expression. That expression is evaluated before every loop iteration.
so something like ForLoopWithDirectionBasedOnStep(minValue: 10, maxValue: 0, step: -2) which would count down from 0 to 10 doesn't print anything because, since 0 < 10, the body of the for statement is never executed.
You need a pre-processing step to change the comparison in the for loop as well as its limits
int Lower = 2;
int Upper = 10;
int Step = -2;
Func<int, bool> comparator = (j) => j <= Upper;
if (Step < 0)
{
var temp = Lower;
Lower = Upper;
Upper = temp;
comparator = (j) => j >= Upper;
}
for(int i=Lower; comparator(i); i+=Step)
{
Console.Write(i + " ");
}
DotNetFiddle
You can do two for loops based on the sign of the step variable:
static void Main(string[] args)
{
int lower = 2;
int upper = 10;
int step = -2;
if (Math.Sign(step) == 1)
{
for (int i = step; i < upper; i += step)
{
Console.WriteLine(string.Format("{0}", i));
}
}
else if (Math.Sign(step) == -1)
{
for (int i = upper; i >= lower; i += step)
{
Console.WriteLine(string.Format("{0}", i));
}
}
Console.ReadLine();
}
}
Note that this code is untested but the idea is to use a Predicate<T> for the loop and switching Upper and Lower if step is negative
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = 2;
if(step < 0){ int temp = Lower; Lower = Upper; Upper = temp;}
Predicate<int> LoopPred = (i =>
{
if(Step < 0)
return i >= Upper;
return i <= Upper;
})
for(int i=Lower; LoopPred(i); i+=Step)
{
Console.Write(i + “ “);
}
You can make a Func delegate to check if the step is negative and invert the bound checking condition.
Here's a sample:
class Program
{
public static void Print(int Lower, int Upper, int Step)
{
Func<int, bool> checkBounds = (i) => i <= Upper;
if (Step < 0)
{
Swap(ref Lower, ref Upper);
checkBounds = (i) => i >= Upper;
}
for (int i = Lower; checkBounds(i); i += Step)
Console.Write($"{i} ");
}
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
static void Main(string[] args)
{
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = -2;
Print(Lower, Upper, Step);
}
}
for(int i=Step>0?Lower:Upper; Step>0? i<=Upper: i>= Lower; i+=Step)
{
Console.Write(i + " ");
}
#john All you need to update the looping conditions.

Method to guess possible combination

For practice I want to write a program that will guess random positions of x and y. For example the first point would be
int x = 0;
int y = 0;
x += rand.Next(0, 4);
y += rand.Next(0, 4);
Then from that random point I will add the another random value to x and y to have a second point. However I want to go back to find those points randomly.
To make the points:
int x = 0;
int y = 0;
List<Point> points = new List<Point>();
for (int i = 0; i < numberOfPointsWanted; i++)
{
x += rand.Next(0, 4);
y += rand.Next(0, 4);
points.Add(new Point(x, y));
}
Now I wish to guess those random points almost as if I did not have them stored in a list. Because each new point relies on its predecessor I assume some sort of recursion would be necessary. Almost like a brute force guessing application that will find those points. I am having trouble completing the method that would be able to guess every possible point given a number of desired points.
This is what I have thus far to find the rounds:
class Program
{
static int nRounds = 2;
static Point[] points = new Point[nRounds];
static Point[] test = { new Point(1, 2), new Point(4, 1) };
static bool CheckArray()
{
for (int i = 0; i < points.Length; i++)
if (points[i] != test[i]) { return false; }
return true;
}
static void PrintArray()
{
for (int i = 0; i < points.Length; i++)
Console.Write("[" + tCount + "]\t" + points[i].X + " : " + points[i].Y + "\t");
Console.Write("\n");
}
static int tCount = 0;
static int rCount = 0;
static void GetRounds(int inX, int inY)
{
for (int x = inX; x < 5; x++)
{
for (int y = inY; y < 5; y++)
{
if (rCount < nRounds)
{
tCount++;
points[rCount] = new Point(x, y);
rCount++;
GetRounds(x, y);
if (CheckArray())
{
PrintArray();
return;
}
PrintArray();
}
}
}
rCount--;
}
static void Main(string[] args)
{
GetRounds(0, 0);
Console.ReadKey();
}
}
}
I am trying to randomly generate points as shown above and then guess them based on a hashed value representing all of those points together.
This is what im expecting to see:
If only guessing two points
Point one :: Point two x and y respectively
x y :: x y
0 0 :: 0 1
0 0 :: 0 2
0 0 :: 0 3
0 0 :: 1 0
0 0 :: 1 1
0 0 :: 1 2
0 0 :: 1 3
0 0 :: 2 0
0 0 :: 2 1
0 0 :: 2 2
0 0 :: 2 3
0 0 :: 3 0
0 0 :: 3 1
0 0 :: 3 2
0 0 :: 3 3
0 1 :: 0 0
0 1 :: 0 1
0 1 :: 0 2
And so on until all possibilities of point one and point two are guessed
I'm not sure if this is exactly what you're looking for, but one way to get all those combinations is to use nested for loops:
for (int ax = 0; ax < 4; ax++)
{
for (int ay = 0; ay < 4; ay++)
{
var pointA = new Point(ax, ay);
for (int bx = 0; bx < 4; bx++)
{
for (int by = 0; by < 4; by++)
{
var pointB = new Point(bx, by);
Console.WriteLine($"{pointA.X} {pointA.Y} :: {pointB.X} {pointB.Y}");
}
}
}
}
Output
You were asking about a solution that would allow a variable number of points to be passed in. This is fairly simple to do - you just keep a List<List<Point>> of the results, and on each iteration you generate a list of possible point values (16 possible values when min is 0 and max is 3), and then generate a new list for every item in the existing results for each Point in the new set.
The problem is the size of the result set. Since a single point has 16 possible combinations of X and Y if we have a min value of 0 and a max value of 3, then for each additional point, we raise 16 to that power. So for 10 points, there are over a billion combinations.
private static List<List<Point>> GetAllCombinations(int min, int max, int count)
{
var results = new List<List<Point>>();
for (int i = 0; i < count; i++)
{
var thisSet = new List<Point>();
for (int x = min; x <= max; x++)
{
for (int y = min; y <= max; y++)
{
thisSet.Add(new Point(x, y));
}
}
// If this is our first time through, we just add each point
// as a single-item list to our results
if (results.Count == 0)
{
foreach (var item in thisSet)
{
results.Add(new List<Point> {item});
}
}
// On subsequent iterations, for each list in our results, and
// for each item in this set, we create a new list for each item,
// adding to it a copy of the existing result list. We clear
// the results in the beginning (after making a copy) and then
// add each new list to it in the inner loop.
else
{
// Make a copy of our existing results and clear the original list
var tempResults = results.ToList();
results.Clear();
foreach (var existingItem in tempResults)
{
foreach (var newPoint in thisSet)
{
// Now we populate our results again with a new set of
// lists for each existingItem and each newPoint
var newItem = existingItem.ToList();
newItem.Add(newPoint);
results.Add(newItem);
}
}
}
}
return results;
}
Example usage:
private static void Main()
{
var results = GetAllCombinations(0, 3, 5);
foreach (var result in results)
{
Console.WriteLine(string.Join(" :: ", result.Select(p => $"{p.X} {p.Y}")));
}
Console.WriteLine("With a min value of 0 and max value of 3, " +
$"5 points generated {results.Count} results.");
GetKeyFromUser("Done! Press any key to exit...");
}
Output

Calculating e number C#

I am trying to calculating e number by that
e = 1 + (1/1! + 1/2! + 1/3! + ..)
User going to select number of trials on that form.
form
int trialNumber = Convert.ToInt32(Math.Round(trialNumberForm.Value, 0));
int factorial = trialNumber;
float factResult = 0;
for (int i = 1; i < trialNumber; i++)
{
for (int b = 1; b < i; b++) //calculates x! here.
{
factorial = factorial * b;
}
factResult = factResult + (1 / factorial);
}
factResult++;
MessageBox.Show(factResult.ToString());
It calculates the result 1 which ever number you selected! I've tried to change variable type to float from double but that didn't fix it. How to act on numbers by formula which I wrote above?
You have no need in factorial (with its integer division and integer overflow problems) at all since
1/(n+1)! == (1/n!)/(n+1)
You can implement e computation as easy as
double factResult = 1; // turn double into float if you want
double item = 1; // turn double into float if you want
for (int i = 1; i < trialNumber; ++i)
factResult += (item /= i);
...
MessageBox.Show(factResult.ToString());
Outcomes:
trial number | e
-------------------------------
1 | 1
2 | 2
3 | 2.5
4 | 2.666666...
5 | 2.708333...
10 | 2.71828152557319
15 | 2.71828182845823
20 | 2.71828182845905
As #kabdulla and #ScottChamberlain said, you are doing integer division where you need a float division :
for (int b = 1; b < i; b++) //calculates x! here.
{
factorial = factorial * b;
}
factResult = factResult + (1 / factorial);
Should be
for (int b = 2; b < i; b++) //calculates x! here.
{
factorial = factorial * b;
}
factResult = factResult + (1.0 / factorial);
Plus I started the for loop at b = 2 because multiplying by 1 is useless.

Why aren't 10 and 100 considered Kaprekar numbers?

I'm trying to do the Modified Kaprekar Numbers problem (https://www.hackerrank.com/challenges/kaprekar-numbers) which describes a Kaprekar number by
Here's an explanation from Wikipedia about the ORIGINAL Kaprekar
Number (spot the difference!): In mathematics, a Kaprekar number for a
given base is a non-negative integer, the representation of whose
square in that base can be split into two parts that add up to the
original number again. For instance, 45 is a Kaprekar number, because
45² = 2025 and 20+25 = 45.
and what I don't understand is why 10 and 100 aren't Kaprekar numbers.
10^2 = 1000 and 10 + 00 = 10
Right?
So my solution
// Returns the number represented by the digits
// in the range arr[i], arr[i + 1], ..., arr[j - 1].
// If there are no elements in range, return 0.
static int NumberInRange(int[] arr, int i, int j)
{
int result = 0;
for(; i < j; ++i)
{
result *= 10;
result += arr[i];
}
return result;
}
// Returns true or false depending on whether k
// is a Kaprekar number.
// Example: IsKaprekar(45) = true because 45^2=2025 and 20+25=45
// Example: IsKaprekar(9) = false because the set of the split
// digits of 7^2=49 are {49,0},{4,9} and
// neither of 49+0 or 4+9 equal 7.
static bool IsKaprekar(int k)
{
int square = k * k;
int[] digits = square.ToString().Select(c => (int)Char.GetNumericValue(c)).ToArray();
for(int i = 0; i < digits.Length; ++i)
{
int right = NumberInRange(digits, 0, i);
int left = NumberInRange(digits, i, digits.Length);
if((right + left) == k)
return true;
}
return false;
}
is saying all the Kaprekar numbers between 1 and 100 are
1 9 10 45 55 99 100
whereas the "right" answer is
1 9 45 55 99
In 100+00 the right is 00, which is wrong because in a kaprekar number the right may start with zero (ex: 025) but cannot be entirely 0.
Therefore you can put a condition in the loop that
if(right==0)
return false;
The reason is because 10 x 10 = 100. Then you substring the right part with a length equals d = 2, that is digit count of original value (10), then the left part would be 1.
So l = 1 and r = 00, l + r = 1, that is not equals to 10.
The same for 100. 100 x 100 = 10000. l = 10, r = 000, so l + r = 10 not equal 100.
Here is my solution in JAVA.
static void kaprekarNumbers(int p, int q) {
long[] result = IntStream.rangeClosed(p, q).mapToLong(Long::valueOf)
.filter(v -> {
int d = String.valueOf(v).length();
Long sq = v * v;
String sqSt = sq.toString();
if (sqSt.length() > 1) {
long r = Long.parseLong(sqSt.substring(sqSt.length() - d));
long l = Long.parseLong(sqSt.substring(0, sqSt.length() - d));
return r + l == v;
} else return v == 1;
}).toArray();
if (result.length > 0) {
for (long l : result) {
System.out.print(l + " ");
}
} else {
System.out.println("INVALID RANGE");
}
}
How about something like this.
static bool IsKaprekar(int k)
{
int t;
for (int digits = new String(k).length(); digits > 0; digits--, t *= 10);
long sq = k * k;
long first = sq / t;
long second = sq % t;
return k == first + second;
}
find a number to divide and mod the square with in order to split it. This number should be a factor of 10 based on the number of digits in the original number.
calculate the square.
split the square.
compare the original to the sum of the splits.

Categories

Resources