I have been converting a Python script to C#, I am 99% there but I am having trouble understanding the following piece of code
# The lower 8-bits from the Xorshift PNR are subtracted from byte
# values during extraction, and added to byte values on insertion.
# When calling deobfuscate_string() the whole string is processed.
def deobfuscate_string(pnr, obfuscated, operation=int.__sub__):
return ''.join([chr((ord(c) operation pnr.next()) & 0xff) for c in obfuscated])
Could you please explain the code above? what does operation pnr.next() do? If you could help maybe convert this method to C# that would be even better but an explanation of the above would be great.
Full source can be found at
https://raw.githubusercontent.com/sladen/pat/master/gar.py
The snippet you provided is not a valid Python code. One cannot write a function name in the place of an infix operator. I think it is meant to be like this:
# The lower 8-bits from the Xorshift PNR are subtracted from byte
# values during extraction, and added to byte values on insertion.
# When calling deobfuscate_string() the whole string is processed.
def deobfuscate_string(pnr, obfuscated, operation=int.__sub__):
return ''.join([chr(operation(ord(c), pnr.next()) & 0xff) for c in obfuscated])
You see, this way it will execute the the operation on ord(c) and pnr.next(). This way the translation to C# is straightforward, operation should be of type Func<int, int, int>.
This might give you an idea:
public static T Next<T>(IEnumerator<T> en) {
en.MoveNext();
return en.Current;
}
public static string deobfuscate_string(IEnumerator<int> pnr, string obfuscated, Func<int, int, int> operation = null) {
if (operation == null) operation = (a, b) => a - b;
return string.Join("", from c in obfuscated select (char)operation((int)c, Next(pnr)));
}
EDIT: added default parameter to deobfuscate_string
The function deobfuscate_string takes an iterable pnr, a string obfuscated and an operation that is by default substract.
For each character c in the string obfuscated
It apply the
operator (substract by default) to the value of the character with
the next element in pnr.
Then it uses & 0xff to ensure result is in range 255
Every thing is then combine in a string.
So, it just encrypt the input by rotating every characters from a known set of rotations.
Notice: The code is not valid as operation cannot by used this way, I just explain the goal here.
Thank you everyone for posting responses, I ended up grabbing a Python debugger and working it through.
private static byte[] deobfuscate_string(XORShift128 pnr, byte[] obfuscated)
{
byte[] deobfuscated = new byte[obfuscated.Length];
for (int i = 0; i < obfuscated.Length; i++)
{
byte b = Convert.ToByte((obfuscated[i] - pnr.next()) & 0xff);
deobfuscated[i] = b;
}
Array.Reverse(deobfuscated);
return deobfuscated;
}
private class XORShift128
{
private UInt32 x = 123456789;
private UInt32 y = 362436069;
private UInt32 z = 521288629;
private UInt32 w = 88675123;
public XORShift128(UInt32 x, UInt32 y)
{
this.x = x;
this.y = y;
}
public UInt32 next()
{
UInt32 t = (x ^ (x << 11)) & 0xffffffff;
x = y;
y = z;
z = w;
w = (w ^ (w >> 19) ^ (t ^ (t >> 8)));
return w;
}
}
Above is that I ended up with
int c;
int f = 20;
c = 5 / 9 * (f - 32);
Console.WriteLine(c);
Console.ReadLine();
If I run this code c ends up being 0, which is wrong. Can anyone tell me why?
Because your calculation is being done in integer type. I believe c is double type variable.
c = 5d / 9 * (f - 32.0);
use 32.0 or 32d so that one of the operands is double, also do the same for 5/9.
Also you need to define c as double.
the problem is in the following line;
5 / 9
because c and f are integers.
For instance, if I asked you to divide 11 to 10; you will tell me the result is 1.1. Assume that you do not know about floating point arithmetic, then you will say either it is not possible to divide 11 to 10; or you will say it is 1. Runtime environment does the same, it says it is 0 since you are declaring an integer.
Habib already explained what is happening. Here is what you could do if you don't want to change c to a float or double:
c = (int)Math.Round(5.0 / 9.0 * (f - 32.0));
I'd like to be able to swap two variables without the use of a temporary variable in C#. Can this be done?
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
// Swap each:
// startAngle becomes: 355.87
// stopAngle becomes: 159.9
C# 7 introduced tuples which enables swapping two variables without a temporary one:
int a = 10;
int b = 2;
(a, b) = (b, a);
This assigns b to a and a to b.
The right way to swap two variables (at the time this question was asked(1)) is:
decimal tempDecimal = startAngle;
startAngle = stopAngle;
stopAngle = tempDecimal;
In other words, use a temporary variable.
There you have it. No clever tricks, no maintainers of your code cursing you for decades to come, no entries to The Daily WTF, and no spending too much time trying to figure out why you needed it in one operation anyway since, at the lowest level, even the most complicated language feature is a series of simple operations.
Just a very simple, readable, easy to understand, t = a; a = b; b = t; solution.
In my opinion, developers who try to use tricks to, for example, "swap variables without using a temp" or "Duff's device" are just trying to show how clever they are (and failing miserably).
I liken them to those who read highbrow books solely for the purpose of seeming more interesting at parties (as opposed to expanding your horizons).
Solutions where you add and subtract, or the XOR-based ones, are less readable and most likely slower than a simple "temp variable" solution (arithmetic/boolean-ops instead of plain moves at an assembly level).
Do yourself, and others, a service by writing good quality readable code.
That's my rant. Thanks for listening :-)
As an aside, I'm quite aware this doesn't answer your specific question (and I'll apologise for that) but there's plenty of precedent on SO where people have asked how to do something and the correct answer is "Don't do it".
(1) Improvements to the language and/or .NET Core since that time have adopted the "Pythonic" way using tuples. Now you can just do:
(startAngle, stopAngle) = (stopAngle, startAngle);
to swap values.
First of all, swapping without a temporary variable in a language as C# is a very bad idea.
But for the sake of answer, you can use this code:
startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;
Problems can however occur with rounding off if the two numbers differ largely. This is due to the nature of floating point numbers.
If you want to hide the temporary variable, you can use a utility method:
public static class Foo {
public static void Swap<T> (ref T lhs, ref T rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
}
Yes, use this code:
stopAngle = Convert.ToDecimal(159.9);
startAngle = Convert.ToDecimal(355.87);
The problem is harder for arbitrary values. :-)
int a = 4, b = 6;
a ^= b ^= a ^= b;
Works for all types including strings and floats.
BenAlabaster showed a practical way of doing a variable switch, but the try-catch clause is not needed. This code is enough.
static void Swap<T>(ref T x, ref T y)
{
T t = y;
y = x;
x = t;
}
The usage is the same as he shown:
float startAngle = 159.9F
float stopAngle = 355.87F
Swap(ref startAngle, ref stopAngle);
You could also use an extension method:
static class SwapExtension
{
public static T Swap<T>(this T x, ref T y)
{
T t = y;
y = x;
return t;
}
}
Use it like this:
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle.Swap(ref stopAngle);
Both ways uses a temporary variable in the method, but you don't need the temporary variable where you do the swapping.
A binary XOR swap with a detailed example:
XOR truth table:
a b a^b
0 0 0
0 1 1
1 0 1
1 1 0
Input:
a = 4;
b = 6;
Step 1: a = a ^ b
a : 0100
b : 0110
a^b: 0010 = 2 = a
Step 2: b = a ^ b
a : 0010
b : 0110
a^b: 0100 = 4 = b
Step 3: a = a ^ b
a : 0010
b : 0100
a^b: 0110 = 6 = a
Output:
a = 6;
b = 4;
In C# 7:
(startAngle, stopAngle) = (stopAngle, startAngle);
Not in C#. In native code you might be able to use the triple-XOR swap trick, but not in a high level type-safe language. (Anyway, I've heard that the XOR trick actually ends up being slower than using a temporary variable in many common CPU architectures.)
You should just use a temporary variable. There's no reason you can't use one; it's not like there's a limited supply.
For the sake of future learners, and humanity, I submit this correction to the currently selected answer.
If you want to avoid using temp variables, there are only two sensible options that take first performance and then readability into consideration.
Use a temp variable in a generic Swap method. (Absolute best performance, next to inline temp variable)
Use Interlocked.Exchange. (5.9 times slower on my machine, but this is your only option if multiple threads will be swapping these variables simultaneously.)
Things you should never do:
Never use floating point arithmetic. (slow, rounding and overflow errors, hard to understand)
Never use non-primitive arithmetic. (slow, overflow errors, hard to understand) Decimal is not a CPU primitive and results in far more code than you realize.
Never use arithmetic period. Or bit hacks. (slow, hard to understand) That's the compiler's job. It can optimize for many different platforms.
Because everyone loves hard numbers, here's a program that compares your options. Run it in release mode from outside Visual Studio so that Swap is inlined. Results on my machine (Windows 7 64-bit i5-3470):
Inline: 00:00:00.7351931
Call: 00:00:00.7483503
Interlocked: 00:00:04.4076651
Code:
class Program
{
static void Swap<T>(ref T obj1, ref T obj2)
{
var temp = obj1;
obj1 = obj2;
obj2 = temp;
}
static void Main(string[] args)
{
var a = new object();
var b = new object();
var s = new Stopwatch();
Swap(ref a, ref b); // JIT the swap method outside the stopwatch
s.Restart();
for (var i = 0; i < 500000000; i++)
{
var temp = a;
a = b;
b = temp;
}
s.Stop();
Console.WriteLine("Inline temp: " + s.Elapsed);
s.Restart();
for (var i = 0; i < 500000000; i++)
{
Swap(ref a, ref b);
}
s.Stop();
Console.WriteLine("Call: " + s.Elapsed);
s.Restart();
for (var i = 0; i < 500000000; i++)
{
b = Interlocked.Exchange(ref a, b);
}
s.Stop();
Console.WriteLine("Interlocked: " + s.Elapsed);
Console.ReadKey();
}
}
<deprecated>
You can do it in 3 lines using basic math - in my example I used multiplication, but simple addition would work also.
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle * stopAngle;
stopAngle = startAngle / stopAngle;
startAngle = startAngle / stopAngle;
Edit: As noted in the comments, this wouldn't work if y = 0 as it would generate a divide by zero error which I hadn't considered. So the +/- solution alternatively presented would be the best way to go.
</deprecated>
To keep my code immediately comprehensible, I'd be more likely to do something like this. [Always think about the poor guy that's gonna have to maintain your code]:
static bool Swap<T>(ref T x, ref T y)
{
try
{
T t = y;
y = x;
x = t;
return true;
}
catch
{
return false;
}
}
And then you can do it in one line of code:
float startAngle = 159.9F
float stopAngle = 355.87F
Swap<float>(ref startAngle, ref stopAngle);
Or...
MyObject obj1 = new MyObject("object1");
MyObject obj2 = new MyObject("object2");
Swap<MyObject>(ref obj1, ref obj2);
Done like dinner...you can now pass in any type of object and switch them around...
With C# 7, you can use tuple deconstruction to achieve the desired swap in one line, and it's clear what's going on.
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
(startAngle, stopAngle) = (stopAngle, startAngle);
For completeness, here is the binary XOR swap:
int x = 42;
int y = 51236;
x ^= y;
y ^= x;
x ^= y;
This works for all atomic objects/references, as it deals directly with the bytes, but may require an unsafe context to work on decimals or, if you're feeling really twisted, pointers. And it may be slower than a temp variable in some circumstances as well.
If you can change from using decimal to double you can use the Interlocked class.
Presumably this will be a good way of swapping variables performance wise. Also slightly more readable than XOR.
var startAngle = 159.9d;
var stopAngle = 355.87d;
stopAngle = Interlocked.Exchange(ref startAngle, stopAngle);
Msdn: Interlocked.Exchange Method (Double, Double)
a = a + b
b = a - b
a = a - b
َ
Beware of your environment!
For example, this doesn’t seem to work in ECMAscript
y ^= x ^= y ^= x;
But this does
x ^= y ^= x; y ^= x;
My advise? Assume as little as possible.
The simple way to swap 2 numbers in just one line:
a=(a+b)-(b=a);
eg: a=1, b=2
Step 1: a=(1+2) - (b=1)
Step 2: a=3-1
=> a=2 and b=1
Efficient way is to use:
C Programming: (x ^= y), (y ^= x), (x ^= y);
Java: x = x ^ y ^ (y = x);
Python: x, y = y, x
Note: Most common mistake people make:
//Swap using bitwise XOR (Wrong Solution in C/C++)
x ^= y ^= x ^= y;
Source: GeeksforGeek
For binary types you can use this funky trick:
a %= b %= a %= b;
As long as a and b are not the exact same variable (e.g. aliases for the same memory) it works.
I hope this might help...
using System;
public class Program
{
public static void Main()
{
int a = 1234;
int b = 4321;
Console.WriteLine("Before: a {0} and b {1}", a, b);
b = b - a;
a = a + b;
b = a - b;
Console.WriteLine("After: a {0} and b {1}", a, b);
}
}
we can do that by doing a simple trick
a = 20;
b = 30;
a = a+b; // add both the number now a has value 50
b = a-b; // here we are extracting one number from the sum by sub
a = a-b; // the number so obtained in above help us to fetch the alternate number from sum
System.out.print("swapped numbers are a = "+ a+"b = "+ b);
Sometimes I wish it were possible to write a function in MSIL inline in C#, similar to how you can write inline assembler in C.
For the record, I once wrote a helper library for C# with various functions for things that were impossible to write in C# but can be written in MSIL (non-zero-based arrays for example). I had this function:
.method public hidebysig static void Swap<T> (
!!T& a,
!!T& b
) cil managed
{
.maxstack 4
ldarg.1 // push a& reference
ldarg.2 // push b& reference
ldobj !!T // pop b&, push b
ldarg.2 // push b& reference
ldarg.1 // push a& reference
ldobj !!T // pop a&, push a
stobj !!T // store a in b&
stobj !!T // store b in a&
ret
}
And no locals needed. Of course this was just me being silly...
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);
If you want to swap 2 string variables:
a = (a+b).Substring((b=a).Length);
An helper method accordingly:
public static class Foo {
public static void SwapString (ref string a, ref string b) {
a = (a+b).Substring((b=a).Length);
}
}
Usage would be then:
string a="Test 1";
string b="Test 2";
Foo.SwapString(a, b);
Here another approach in one line:
decimal a = 159.9m;
decimal b = 355.87m;
a = b + (b = a) - b;
Here is some different process to swap two variables
//process one
a=b+a;
b=a-b;
a=a-b;
printf("a= %d b= %d",a,b);
//process two
a=5;
b=10;
a=a+b-(b=a);
printf("\na= %d b= %d",a,b);
//process three
a=5;
b=10;
a=a^b;
b=a^b;
a=b^a;
printf("\na= %d b= %d",a,b);
//process four
a=5;
b=10;
a=b-~a-1;
b=a+~b+1;
a=a+~b+1;
printf("\na= %d b= %d",a,b);
this model is very useful
var a = 10;
var b = 20;
(int a,int b) c = (a,b);
a = c.b ;
b = c.a ;
var a = 15;
var b = -214;
a = b | !(b = a);
This works great.
Very simple code for swapping two variables:
static void Main(string[] args)
{
Console.WriteLine("Prof.Owais ahmed");
Console.WriteLine("Swapping two variables");
Console.WriteLine("Enter your first number ");
int x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter your first number ");
int y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("your vlaue of x is="+x+"\nyour value of y is="+y);
int z = x;
x = y;
y = z;
Console.WriteLine("after Swapping value of x is="+x+"/nyour value of y is="+y);
Console.ReadLine();
}
You can try the following code. It is much more better than the other code.
a = a + b;
b = a - b;
a = a - b;