Post-increment x by n (n != 1) - c#

So, if I execute the following code...
int x = 0;
Debug.WriteLine(x++);
Debug.WriteLine(x += 4);
Debug.WriteLine(x);
... I get 0, 5, and 5, respectively. What I'd like to get, however is 0, 1, and 5. Is there any way to do a post-increment by n in C#? Or do I have to write out the += as its own statement?
Just for context, what I'm actually doing is a bunch of BitConverter operations on a buffer, and it'd be really nice to have each one as a self-sufficient statement where the offset is incremented by the size of the data type being converted to. That way, if the buffer format is later changed, I can just add or remove the one line without having to worry about any of the surrounding code.

You should be able to abuse Interlocked.Exchange to get the old value of a variable while at the same time replacing its value:
Debug.WriteLine(Interlocked.Exchange(ref x, x+4));
in other words, replace the value of variable x with x + 4 but return the previous value of x.
Edit:
Disassembly shows this "increment by 4 and swap" is done in 4 instructions - no call needed at all, so performance should be good:
Interlocked.Exchange(ref x, x + 4);
0000005e mov eax,dword ptr [rbp+2Ch]
00000061 add eax,4
00000064 xchg eax,dword ptr [rbp+2Ch]
00000067 mov dword ptr [rbp+28h],eax
The non-intuitive nature of this (and other) solutions probably boils down to the violation of the CQS principle - we are mutating a variable and returning a value all at once, i.e. not something we should be doing in the mainstream.

As far as I know it's not possible. You could write your wrapper method like that:
static void ExecuteWithPost(ref int value, Action<int> operation, Func<int, int> postOperation)
{
operation(value);
value = postOperation(value);
}
and use it:
int i = 0;
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x + 1);
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x + 4);
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x);
Prints what you want.
The wrapper method can be generic to make it work with types other than int:
static void ExecuteWithPost<T>(ref T value, Action<T> operation, Func<T, T> postOperation)
{
operation(value);
value = postOperation(value);
}

Operator ++ is short form of x = x + 1; so using += is not a bad idea:
If I understand you correctly:
int x = 0;
Debug.WriteLine(x++); //return 0
Debug.WriteLine(x); //return 1
Debug.WriteLine(x += 4); //return 5
I would suggest you to use operator += because any other way operator overloading or something else; will just be a overhead.

Related

.net core switch expression incrementing with wrong value

I was playing around with my intcode computer implementation (from advent of code 2019) and found that when I implemented the switch (to select which operation to execute) it was taking the wrong value.
The following code demonstrates this.
InstructionPointer had a value of 2, opcode had the value of 6 which means that OpcodeJumpIfFalse will be used. Function Jif() is called just fine, and it returns a value, in my case it was returning 0. Jif() also modified the value of InstructionPointer, changing its value to 9. The InstructionPointer would the be increased by 0 (return value of Jif()) and I would expect its value to be 9, but its value would go back to being 2.
InstructionPointer += opcode switch
{
OpcodeAdd => Add(),
OpcodeMultiply => Mul(),
OpcodeInput => Inp(),
OpcodeOutput => Out(),
OpcodeJumpIfTrue => Jit(),
OpcodeJumpIfFalse => Jif(),
OpcodeLessThan => Let(),
OpcodeEquals => Equ(),
OpcodeAdjustRelativeBase => Arb(),
OpcodeHalt => End(),
_ => throw new ArgumentOutOfRangeException()
};
Minimal example which shows same behavior:
int j = 2;
int i = 1;
int A()
{
j = 10;
return 0;
}
j += i switch
{
1 => A(),
_ => throw new Exception()
};
Console.WriteLine(j);
I did notice that Resharper (in the minimal example) is telling me the assignment is unused in A().
My question is, why does this happen? Is the value of j "captured" before the switch? Is this expected behavior?
For now, I have changed my code to use a temporary variable, which resolves the issue, but I would still like to know what is going on here.
Remember that the compound assignment operator a += b is the same as a = a + b (except that a is evaluated only once), see ยง7.17.2 of the spec.
Here's a slightly simpler example which doesn't use a switch, and has the same effect:
int j = 2;
int A()
{
j = 10;
return 0;
}
j = j + A();
If you don't want to think in terms of local functions, you can also write this as a class:
class C
{
private int j;
public void Test()
{
j = 2;
j = j + A();
}
private int A()
{
j = 10;
return 0;
}
}
The compiler will:
Start by evaluating j + A():
Push the current value of j, which is 2, onto the stack
Call A(), which sets j to 10 and returns 0
Push the return value of A(), which is 0, onto the stack
Add together the two values on the stack: 2 + 0
Assign this value to j
If you write the assignment the other way around, as j = A() + j, then its final value is 10. If you follow the same sequence of steps as above, you'll see why.
This general approach -- changing a variable as a side-effect of an expression which also changes that variable -- is a bad idea. It leads to very hard-to-understand code.

Fast and low-memory-consumption way to read in pair of numbers from file and process them?

Okay, so this is my challenge taken from CodeEval. I have to read numbers from a file that is formatted in a standard way, it has a pair of numbers separated by a comma on each line (x, n). I have to read in the pair values and process them, then print out the smallest multiple of n which is greater than or equal to x, where n is a power of 2.
EXACT REQUIREMENT: Given numbers x and n, where n is a power of 2, print out the smallest multiple of n which is greater than or equal to x. Do not use division or modulo operator.
I have come up with a number of solutions, but none of them satisfy the computer's conditions to let me pass the challenge. I only get a partial completion with scores that vary from 30 to 80 (from 100).
I'm assuming that my solutions do not pass the speed but more likely the memory-usage requirements.
I would greatly appreciate it if anyone can enlighten me and offer some better, more efficient solutions.
Here are two of my solutions:
var filePath = #"C:\Users\myfile.txt";
int x;
int n;
using (var reader = new StreamReader(filePath))
{
string numsFile = string.Empty;
while ((numsFile = reader.ReadLine()) != null)
{
var nums = numsFile.Split(',').ToArray();
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
}
<<<>>>
var fileNums = File.ReadAllLines(filePath);
foreach (var line in fileNums)
{
var nums = line.Split(',').ToArray();
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
Method to check numbers
public static int DangleNumbers(int x, int n)
{
int m = 2;
while ((n * m) < x)
{
m += 2;
}
return m * n;
}
I'm fairly new to C# and programming but these two ways I found to get the best score from several others I have tried. I'm thinking that it's not too optimal for a new string to be created on each iteration, nor do I know how to use a StringBuilder and get the values into an Int from it.
Any pointers in the right direction would be appreciated as I would really like to get this challenge passed.
The smallest multiple of n that is larger or equal to x is likely this:
if(x <= n)
{
return n;
}
else
{
return x % n == 0 ? x : (x/n + 1) * n;
}
As x and n are integers, the result of x/n will be truncated (or effectively rounded down). So the next integer larger than x that is a multiple of n is (x/n + 1) * n
Since you missed the requirements, the modulo version was the most obvious choice. Though you still got your method wrong. m = 2 would not result in the smallest being returned but it could actually be the double of the smallest if n is already larger than x.
x = 7, n = 8 would get you 16 instead of 8.
Also adding 2 to m would result in a similar problem.
x = 5, n = 2 would get you 8 instead of 6.
use the following method instead:
public static int DangleNumbers(int x, int n)
{
int result = n;
while(result < x)
result += n;
return result;
}
Still capable of begin optimized but at least right according to the (now) stated constraints.
I have tried to improve the solution with some suggestions from you guys and take the variables outside the loop and drop the ToArray() call which was redundant.
static void Main(string[] args)
{
var filePath = #"C:\Users\sorin\Desktop\sorvas.txt";
int x;
int n;
string[] nums;
using (var reader = new StreamReader(filePath))
{
string numsFile = string.Empty;
while ((numsFile = reader.ReadLine()) != null)
{
nums = numsFile.Split(',');
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
}
}
public static int DangleNumbers(int x, int n)
{
int m = 2;
while ((n * m) < x)
{
m += 2;
}
return m * n;
}
So it looks like this. The thing is that even if now the numbers have slightly improved, I got a lower score.
May it be their system to blame ?
Using the first option of reading line by line (rather than reading all lines) is clearly going to use less memory (except potentially in the case where the file is very small (eg "1,1") in which case the overhead of the reader may cause problems but at that point the memory used is probably irrelevant.
Likewise declaring the variables outside the loop is generally better but in this case since the objects are value types I'm not sure it makes a difference.
Lastly the most efficient way of doing your DangleNumbers method is probably using bitwise logic operators and the fact that n is always a power of 2. Here is my attempt:
public static int DangleNumbers3(int x, int n)
{
return ((x-1) & ~(n-1))+n;
}
Essentially it relies on the fact that in binary a power of n is always a 1 followed by zero or more zeros. Thus a multiple of n will always end in that same number of zeros. So if n has M zeros after the one then you can take the binary form of x and if it already ends in M zeros then you have your answer. Otherwise you zero out the last M digits at which point you have the multiple of n that is just under x and then you add 1.
In the code ~(n-1) is a bitmask that has M zeros at the end and the leading digits are all 1. Thus when you AND it with a number it will zero out the trailing digits. I apply this to (x-1) to avoid having to do the check for if it is already the answer and have special cases.
It is important to note that this only works because of the special form of n as a power of 2. This method avoids the need for any loops and thus should run much faster (it has five operations total and no branching at all compared to other looping methods which will tend to have at the very least an operation and a comparison per loop.

Pre- & Post Increment in C#

I am a little confused about how the C# compiler handles pre- and post increments and decrements.
When I code the following:
int x = 4;
x = x++ + ++x;
x will have the value 10 afterwards. I think this is because the pre-increment sets x to 5, which makes it 5+5 which evaluates to 10. Then the post-increment will update x to 6, but this value will not be used because then 10 will be assigned to x.
But when I code:
int x = 4;
x = x-- - --x;
then x will be 2 afterwards. Can anyone explain why this is the case?
x-- will be 4, but will be 3 at the moment of --x, so it will end being 2, then you'll have
x = 4 - 2
btw, your first case will be x = 4 + 6
Here is a small example that will print out the values for each part, maybe this way you'll understand it better:
static void Main(string[] args)
{
int x = 4;
Console.WriteLine("x++: {0}", x++); //after this statement x = 5
Console.WriteLine("++x: {0}", ++x);
int y = 4;
Console.WriteLine("y--: {0}", y--); //after this statement y = 3
Console.WriteLine("--y: {0}", --y);
Console.ReadKey();
}
this prints out
x++: 4
++x: 6
y--: 4
--y: 2
Lets have a look at the IL that gets generated from that statement
IL_0002: ldloc.0
Loads the value of x onto the stack. Stack => (4)
IL_0003: dup
Duplicates the topmost item on the stack. Stack => (4, 4)
IL_0004: ldc.i4.1
Push 1 onto the stack. Stack => (1, 4, 4)
IL_0005: sub
Subtract the two top values and push result onto the stack. Stack => (3, 4)
IL_0006: stloc.0
Store the topmost value of the stack back to x. Stack => (4)
IL_0007: ldloc.0
Load the value of x back into the stack. Stack => (3, 4)
IL_0008: ldc.i4.1
Load the value 1 onto the stack. Stack => (1, 3, 4)
IL_0009: sub
Subtract the two. Stack => (2, 4)
IL_000A: dup
Duplicate the top value => (2, 2, 4)
IL_000B: stloc.0
Store the top value back to x. Stack => (2, 4)
IL_000C: sub
Subtract the two top values. Stack => (2)
IL_000D: stloc.0
Store this value back into x. x == 2
From your comment:
I thought that post- and pre-increments are executed after / before evaluation of the complete codeline - but they are executed after / before the evaluation of each item in the expression.
Your misunderstanding is an extremely common one. Note that in some languages, like C, it is not specified when the side effect becomes visible and it is therefore legal, but not required, for your statement to be true in C.
This is not the case in C#; in C# side effects of code on the left side of an expression are always observed to happen before code on the right side executes (from a single thread; in multithreaded scenarios all bets are off.)
For a more detailed explanation of what the increment operators do in C#, see:
What is the difference between i++ and ++i?
There are a great many additional links there to articles I've written on this often-misunderstood topic.
The most interesting thing that you'll get a completely different answer with C++.Net compiler.
int x = 4;
x = x++ + ++x; // x = 11
x = 4;
x = x-- - --x; // x = -1
Of course the difference in results is determined by different semantics - it seems normal. But despite the understanding the fact that two .net compilers don't behave in a similar manner for such basic things confuses me too.
In this example,
int x = 4;
x = x++ + ++x;
you can break it like:
x = 4++; which is = 5
x = 4 + ++5; which is 4 + 6
x = 10
Similarly,
int x = 4;
x = x-- - --x;
Here,
x = 4--; which is = 3
x = 4 - --3; which is 4 - 2
x = 2
Simply putting you can say, replace the current value of x, but for every ++ or -- add/subtract a value from x.
I think the explanation for the ++ + ++ case is wrong:
command...........value of x
..................undefined
int x=4 ..........4
x++...............5 (first summand is 4)
++x...............6 (second summand is 6)
x=summand1+summand2 ..4+6=10
Analogous the explanation for the -- - -- case is
command...........value of x
..................undefined
int x=4 ..........4
x--...............3 (subtactor is 4)
--x...............2 (subtrahend is 2)
x=subtractor-subtrahend ..4-2=10

Aggregate lambda expressions

int sum0 = 0;
for (int i = 0; i < 10; i++)
{
sum0 += i;
}
int sum1 = Enumerable.Range(0, 10).Sum();
int sum2 = Enumerable.Range(0, 10).Aggregate((x, y) => x + y);
int sum3 = Enumerable.Range(0, 10).Aggregate(0, (x, y) => x + y);
All of the above 4 expressions are doing the same thing: find sum from 0 to 10. I understand the calculation of sum0 and sum1. But what are sum2 and sum3? Why the lambda uses two parameters (x, y) here?
Expanding on bdukes' answer, the lambda takes
( x = [value of last lambda expression], y = [next value] ) => x+y
and sum3 allows you to set the initial x value.
The Enumerable.Aggregate method expects a function that takes the current value of the aggregation and a value from the enumeration. The overload for sum3 also provides a starting value for the aggregation.
X is holding the current total, Y is being added to it for each element.
Foreach(y)
X = X + Y;
The Aggregate extension methods take a function (Func<T1,T2,TResult>) that calculates an aggregate..
The function specified for sum2 is one that adds x to y, for every supplied x and y (that is it sums all the items in the enumeration).
The additional parameter for sum3 is an accumulator - a value that is to be added for each operation - as this is 0, it is essentially summing up all the items in the enumeration without any additional values.
sum2 uses a custom function x + y to aggregate each element of the list. The aggregation starts with the default value for an integer 0 and adds the first element to it. It then takes that value and adds the next element, and so on, until it runs out of elements. It then returns the final figure.
sum3 does exactly the same as sum2 but it also explicitly starts the aggregation with a specific value of 0.
Semantically all three are the same - as presented here - but by varying the aggregation function and the initial starting value you can generate all sorts of custom aggregations.
Another way of looking at it is that .Sum() is simply short-hand for .Aggregate(0, (x, y) => x + y);.
x is the variable that "accumulates" the values so its value is
step 1) 1
step 2) 3
step 3) 6
step 4) 10
and so on...
the 0 in the sum3 is the starting value :) (which is redundant since 0 is the default value for int)
The parameter x holds the aggregation, and y is the next enumeration item.
string sentence = "the quick brown fox jumps over the lazy dog";
// Split the string into individual words.
string[] words = sentence.Split(' ');
// Prepend each word to the beginning of the
// new sentence to reverse the word order.
string reversed = words.Aggregate((workingSentence, next) =>
next + " " + workingSentence);
Console.WriteLine(reversed);
// This code produces the following output:
//
// dog lazy the over jumps fox brown quick the
from http://msdn.microsoft.com/en-us/library/bb548651.aspx

What is the simplest way to initialize an Array of N numbers following a simple pattern?

Let's say the first N integers divisible by 3 starting with 9.
I'm sure there is some one line solution using lambdas, I just don't know it that area of the language well enough yet.
Just to be different (and to avoid using a where statement) you could also do:
var numbers = Enumerable.Range(0, n).Select(i => i * 3 + 9);
Update This also has the benefit of not running out of numbers.
Using Linq:
int[] numbers =
Enumerable.Range(9,10000)
.Where(x => x % 3 == 0)
.Take(20)
.ToArray();
Also easily parallelizeable using PLinq if you need:
int[] numbers =
Enumerable.Range(9,10000)
.AsParallel() //added this line
.Where(x => x % 3 == 0)
.Take(20)
.ToArray();
const int __N = 100;
const int __start = 9;
const int __divisibleBy = 3;
var array = Enumerable.Range(__start, __N * __divisibleBy).Where(x => x % __divisibleBy == 0).Take(__N).ToArray();
int n = 10; // Take first 10 that meet criteria
int[] ia = Enumerable
.Range(0,999)
.Where(a => a % 3 == 0 && a.ToString()[0] == '9')
.Take(n)
.ToArray();
I want to see how this solution stacks up to the above Linq solutions. The trick here is modifying the predicate using the fact that the set of (q % m) starting from s is (s + (s % m) + m*n) (where n represent's the nth value in the set). In our case s=q.
The only problem with this solution is that it has the side effect of making your implementation depend on the specific pattern you choose (and not all patterns have a suitable predicate). But it has the advantage of:
Always running in exactly n iterations
Never failing like the above proposed solutions (wrt to the limited Range).
Besides, no matter what pattern you choose, you will always need to modify the predicate, so you might as well make it mathematically efficient:
static int[] givemeN(int n)
{
const int baseVal = 9;
const int modVal = 3;
int i = 0;
return Array.ConvertAll<int, int>(
new int[n],
new Converter<int, int>(
x => baseVal + (baseVal % modVal) +
((i++) * modVal)
));
}
edit: I just want to illustrate how you could use this method with a delegate to improve code re-use:
static int[] givemeN(int n, Func<int, int> func)
{
int i = 0;
return Array.ConvertAll<int, int>(new int[n], new Converter<int, int>(a => func(i++)));
}
You can use it with givemeN(5, i => 9 + 3 * i). Again note that I modified the predicate, but you can do this with most simple patterns too.
I can't say this is any good, I'm not a C# expert and I just whacked it out, but I think it's probably a canonical example of the use of yield.
internal IEnumerable Answer(N)
{
int n=0;
int i=9;
while (true)
{
if (i % 3 == 0)
{
n++;
yield return i;
}
if (n>=N) return;
i++;
}
}
You have to iterate through 0 or 1 to N and add them by hand. Or, you could just create your function f(int n), and in that function, you cache the results inside session or a global hashtable or dictionary.
Pseudocode, where ht is a global Hashtable or Dictionary (strongly recommend the later, because it is strongly typed.
public int f(int n)
{
if(ht[n].containsValue)
return ht[n];
else
{
//do calculation
ht[n] = result;
return result;
}
}
Just a side note. If you do this type of functional programming all the time, you might want to check out F#, or maybe even Iron Ruby or Python.

Categories