CompressedInt Write? - actionscript-3

public static function Read(param1:IDataInput) : int
{
var _loc2_:* = 0;
var _loc3_:int = param1.readUnsignedByte();
var _loc4_:* = (_loc3_ & 64) != 0;
var _loc5_:int = 6;
_loc2_ = _loc3_ & 63;
while(_loc3_ & 128)
{
_loc3_ = param1.readUnsignedByte();
_loc2_ = _loc2_ | (_loc3_ & 127) << _loc5_;
_loc5_ = _loc5_ + 7;
}
if(_loc4_)
{
_loc2_ = int(-_loc2_);
}
return _loc2_;
}
someone can help me with write thing?
about to use in as3 server based but got only read thing

As #Organis correctly said "there's no telling how to compose a reverted algorithm."
The only obvious things are listed below, so you'll have to do a lot of testing to get it right (that's how reverse engineering works, and it might take days or weeks). Good luck.
Assessment:
(1)
public static function Read(param1:IDataInput) : int
Look like it expects a (byte) array with two entries. I suspect you should write a Short (in hex formnat) but it'll be easier to just write two separate decimal values (since a Short is a value that spreads over two bytes).
public static function Write(val1 :int, val2 :int, targetBA :ByteArray) : void
{
targetBA.length = 2;
targetBA.position = 0;
targetBA.writeByte( val1 );
targetBA.writeByte( val2 );
//# target ByteArray can now be "Read" by the other function as "param1"
}
As for the Read side...
Since the function returns a value to update some var, you should use as:
myResult = Read( targetBA );
Where myResult gets the function's returned _loc2_ result.
(2)
var _loc4_:* = ( (_loc3_ & 64) != 0 );
This will give either a 0 or 64. Is 0 if lower than 64, or else is 64 if equal or higher.
This is likely a quick shortcut to setting a Boolean like:
var _loc4_ :Boolean;
if (_loc3_ >= 64) { _loc4_ = true}
else { _loc4_ = false; }
(3)
_loc2_ = _loc3_ & 63;
Where _loc2_ is set as an integer of either 0 or 63.
(4)
while(_loc3_ & 128)
I don't know what this is trying to achieve. (_loc3_ & 128) is either 0 or 128.
This While(0) or While(128) loop will run forever and there isn't any stopping break; at the end.
(5)
_loc2_ = _loc2_ | (_loc3_ & 127) << _loc5_;
This updates _loc2_ with two values. The current loc2 value is combined with a modified loc3 value.
(6)
if(_loc4_)
Likely means if( _loc4_ == true )...

Related

Autokey Encryption

I am working on a project to write to and read from a TP Link / Kaza power strip or smart plug.
The data that is sent is encrypted json that has been "autokey encrypted".
So far I have been able to convert a typescript encrypt function and it works well. I get the expected result. However, I need to add a "header" to my encrypted data. That data is 3 null bytes followed by a byte that is a measure of the length of the encrypted bytes.
The typescript example has this bit of code to "encrypt with headers", however, I've hit a bit of a wall trying to convert it to something usable. Can someone nudge me along the path ?
First are the two typescript functions: (borrowed from https://github.com/plasticrake/tplink-smarthome-crypto/blob/master/src/index.ts)
/**
* Encrypts input where each byte is XOR'd with the previous encrypted byte.
*
* #param input - Data to encrypt
* #param firstKey - Value to XOR first byte of input
* #returns encrypted buffer
*/
export function encrypt(input: Buffer | string, firstKey = 0xab): Buffer {
const buf = Buffer.from(input);
let key = firstKey;
for (let i = 0; i < buf.length; i += 1) {
// eslint-disable-next-line no-bitwise
buf[i] ^= key;
key = buf[i];
}
return buf;
}
/**
* Encrypts input that has a 4 byte big-endian length header;
* each byte is XOR'd with the previous encrypted byte.
*
* #param input - Data to encrypt
* #param firstKey - Value to XOR first byte of input
* #returns encrypted buffer with header
*/
export function encryptWithHeader(
input: Buffer | string,
firstKey = 0xab
): Buffer {
const msgBuf = encrypt(input, firstKey);
const outBuf = Buffer.alloc(msgBuf.length + 4);
outBuf.writeUInt32BE(msgBuf.length, 0);
msgBuf.copy(outBuf, 4);
return outBuf;
}
Second is what I have so far.
// This part works well and produces the expected results
String encrypt(String input)
{
int16_t firstKey = 0xab;
String buf;
int key;
int i;
buf = input;
key = firstKey;
i = 0;
for (;i < buf.length();(i = i + 1))
{
buf[i] ^= key;
key = buf[i];
}
return buf;
}
// This does not function yet, as I'm pretty lost..
// This was orginally converted from typescript with https://andrei-markeev.github.io/ts2c/
// I started work on converting this, but ran into errors I don't know how to solve.
String encryptWithHeader(String input){
String msgBuf;
String outBuf;
int16_t firstKey = 0xab;
char * null = NULL;
msgBuf = encrypt(input);
outBuf = msgBuf.length() +1;
//this is where I got lost...
assert(null != NULL);
null[0] = '\0';
strncat(null, outBuf, msgBuf.length());
str_int16_t_cat(null, 4);
outBuf = msgBuf + 4
return outBuf;
}
Finally, the data:
//this is the unencrypted json
String offMsg = "{\"system\":{\"set_relay_state\":{\"state\":0}}}";
//current encrypt function produces:
d0f281f88bff9af7d5ef94b6c5a0d48bf99cf091e8b7c4b0d1a5c0e2d8a381f286e793f6d4eedea3dea3
//the working "withheaders" should produce:
00002ad0f281f88bff9af7d5ef94b6c5a0d48bf99cf091e8b7c4b0d1a5c0e2d8a381f286e793f6d4eedea3dea3
Admittedly my C/C++ ability is very limited and I can spell typescript, that's about all. I have a very extensive history with PHP. As useful as that is. So, I understand the basics of data structures and whatnot, but I'm venturing off into areas I've never been in. Any help would be greatly appreciated.
It looks like the encryption is fairly simple: write the current character XORed with the key to the buffer and make that newly written character the new key. It also looks like the "withHeaders" version adds the length of the encrypted string as a 4 byte integer to the start of the buffer. I think it might be easier to allocate a character array and pass that array to a function that writes the result to that buffer. For example:
void encryptWithHeader(byte buffer[], int bufferLength, byte key, String message) {
int i;
uint32_t messageLength = message.length();
Serial.println(message);
Serial.println(message.length());
// check that we won't overrun the buffer
if ( messageLength + 5 < bufferLength) {
buffer[0] = messageLength >> 24 & 0xFF;
buffer[1] = messageLength >> 16 & 0xFF;
buffer[2] = messageLength >> 8 & 0xFF;
buffer[3] = messageLength & 0xFF;
for (i = 0; i < messageLength; i++) {
buffer[i + 4] = message[i] ^ key;
key = buffer[i + 4];
}
}
else { // we would have overrun the buffer
Serial.println("not enough room in buffer for message");
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
byte theBuffer[64];
int i;
String offMsg = "{\"system\":{\"set_relay_state\":{\"state\":0}}}";
encryptWithHeader(theBuffer, 64, 0xab, offMsg);
// now print it out to check
for (i = 0; i < offMsg.length() + 4; i++) {
if (theBuffer[i] < 0x10) // adds an extra zero if a byte prints as on1y 1 char
Serial.print("0");
Serial.print(theBuffer[i], HEX);
}
while (true)
;
}
If you want to send the character buffer to a remote device you can send it out one byte at a time:
for (i = 0; i < offMsg.length() + 4; i++)
Serial.write(theBuffer[i]);

How to interpolate between numerial data table values in Dart ( actually in any language )

I have a simple data table with x and y values, something like this:
x y
-10 -0.505
-9 -0.422
-8 -0.335
-7 -0.243
-6 -0.148
-5 -0.051
-4 0.046
-3 0.144
-2 0.242
-1 0.34
0 0.539
1 0.658
2 0.773
3 0.716
4 0.8
5 0.88
6 0.952
7 1.016
8 1.071
9 1.116
10 1.15
The x step size as well as the min and max values might be different.
I am looking for a built-in functionality to interpolate between these values.
So I need a function which takes the x values and returns the corresponding y value. When there is no exact match, I need the function to linearly interpolate between the two closest values.
Of course I could write my own function but I feel like there might be an easy solution, maybe even built-in in Dart.
I appreciate any help.
Thanks & cheers
Tobi
You can use the SplayTreeMap<double, double> to store your values. The key represents the range to search within.Then use an interpolation function as shown below:
var kEfficiencyMotorsFullLoad = SplayTreeMap<double, double>.from({
0.75: .825,
1.1: .841,
1.5: .853,
2.2: .867,
3.0: .877,
4.0: .886,
5.5: .896,
7.5: .904,
11.0: .914,
15.0: .921,
18.5: .926,
22.0: .930,
30.0: .936,
});
double linearInterpolate(double target, SplayTreeMap<double, double> values) {
if (values.containsKey(target)) return values[target]!;
double? xa = values.lastKeyBefore(target);
double? xb = values.firstKeyAfter(target);
//very small key
if (xa != null && xb == null) return values[xa]!;
//very large key
if (xa == null && xb != null) return values[xb]!;
//strange error
if (xa == null && xb == null)
throw Exception(
"number was not found in the SplayTreeMap, check if it is not empty");
double ya = values[xa] ?? 0;
double yb = values[xb] ?? 0;
return ya + ((yb - ya) * ((target - xa!) / (xb! - xa)));
}
There might be some package on pub.dev that does it already, but I'd use a SplayTreeMap and its lastKeyBefore and firstKeyAfter methods to find the surrounding points and then interpolate between them. For example:
import 'dart:collection' show SplayTreeMap;
import 'dart:math' show Point;
/// Returns the y-coordinate for the specified x-coordinate on the line defined
/// by two given points.
double _interpolate(Point<double> p0, Point<double> p1, double x) {
// y - y0 = m * (x - x0)
var m = (p1.y - p0.y) / (p1.x - p0.x);
return m * (x - p0.x) + p0.y;
}
class InterpolatingMap {
final SplayTreeMap<double, double> _data;
InterpolatingMap(Map<double, double> data)
: _data = SplayTreeMap<double, double>.of(data);
double operator [](double x) {
var value = _data[x];
if (value != null) {
return value;
}
if (_data.isEmpty) {
throw StateError('InterpolatingMap is empty');
}
double? lower = _data.lastKeyBefore(x);
double? upper = _data.firstKeyAfter(x);
assert(lower != null || upper != null);
double x0;
double x1;
if (lower == null) {
// `x` is to the left of the left-most data point. Extrapolate from the
// first two entries.
x0 = upper!;
x1 = _data.firstKeyAfter(upper) ?? x0;
} else if (upper == null) {
// `x` is to the right of the right-most data point. Extrapolate from the
// last two entries.
x1 = lower;
x0 = _data.lastKeyBefore(lower) ?? x1;
} else {
x0 = lower;
x1 = upper;
}
return _interpolate(
Point<double>(x0, _data[x0]!),
Point<double>(x1, _data[x1]!),
x,
);
}
}
void main() {
var interpolatingMap = InterpolatingMap({
0: 1,
1: 2,
2: 1,
});
print(interpolatingMap[-1]); // Prints: 0
print(interpolatingMap[0]); // Prints: 1
print(interpolatingMap[0.25]); // Prints: 1.25
print(interpolatingMap[0.5]); // Prints: 1.5
print(interpolatingMap[0.75]); // Prints: 1.75
print(interpolatingMap[1]); // Prints: 2
print(interpolatingMap[1.5]); // Prints: 1.5
print(interpolatingMap[3]); // Prints: 0
}
Note that InterpolatingMap in the above implementation is a bit of a misnomer since it also will extrapolate values outside the data range. (It should be trivial to make it throw an exception if you want to disable extrapolation, however.) It also doesn't implement the Map interface (which is left as an exercise for readers who care about that).
I would probably use binary search to find the matching range, then interpolate from that.
You can use the lowerBound method from package:collection to find the largest element less then or equal to the element you search for.
Something like:
import"package:collection/collection.dart";
double interpolate(List<num> keyPoints, List<num> values, num x) {
if (keyPoints.length < 2) {
throw ArgumentError.value(keyPoints, "keyPoints",
"Needs at least two points to interpolate");
}
if (keyPoints.length != values.length) {
throw ArgumentError.value(values, "values",
"Must have the same number of elements as the key points");
}
var p = keyPoints.lowerBound(x);
if (p > keyPoints.length - 2) p = keyPoints.length - 2;
var startPosition = keyPoints[p];
var endPosition = keyPoints[p + 1];
var startValue = values[p];
var endValue = values[p + 1];
return (x - startPosition) / (endPosition - startPosition) * (endValue - startValue);
}
This will interpolate the value when x is between two key-points, and extrapolate the first or last range if the x value is outside the key-point range.

Converting alpha percent to RGBA hex in AS3?

Say I have the following setup in my AS code:
var color:String = "#0000FF"; //blue
var alpha:Number = 42; //42% or 42/100
How would I combine those into a #RRGGBBAA hex color? I've been Googling around and trying to figure out hexadecimal conversion and notation without luck.
There are two ways you could do this.
One is a bit hacky using int's toString() method and passing 16 as the radix/base:
var rgb:int = (int)("#0000FF".replace("#","0x"));//convert the string to a int (note you can type hex ints starting with 0x (e.g. 0x0000FF)
var a:int = 42;
var rgba:int = int("0x"+rgb.toString(16) + a.toString(16));
or the less hacky and probably faster computationally method using bitwise operators:
var rgb:uint = (uint)("#0000FF".replace("#","0x"));
//extract components using bit shifting (>>) and masking (0xFF)
var r:uint = rgb >> 16 & 0xFF;
var g:uint = rgb >> 8 & 0xFF;
var b:uint = rgb >> 0 & 0xFF;//same as rgb >> 0xFF, just added >> 0 to make the shift obvious
var a:uint = 42;
var rgba:uint = r << 24 | g << 16 | b << 8 | a;
var argb:uint = a << 24 | r << 16 | g << 8 | b;
//test
trace(rgba.toString(16));
trace(argb.toString(16));
Note that using toString(16) in the trace above is to make it useful to us humans,
you'd use the actual uint value when working with hex color values.
Also note that you might want to use ARGB in as3 sometimes, for example when working with BitmapData:
addChild(new BitmapData(100,100,true,0x2a0000ff));//add a 42% transparent blue box (100x100 px)
UPDATE
The above bitshift code snippet actually explains rgb extraction in detail which helps understand things better, but you already have rgb, so it's a matter of adding the alpha component. Also you mentioned 42% which is not the same as on a 0 to 255 scale. Therefore bellow lies your answer:
var rgb:uint = (uint)("#0000FF".replace("#","0x"));
var a:uint = (uint)((42 * .01) * 255);//map 42 from 0<>100 to 0<>255 ( *.01 is the same as / 100 but faster
var rgba:uint = rgb << 8 | a;
var argb:uint = a << 24 | rgb;
Regarding speed, if I run the two different conversion methods a million times here are execution times:
using strings (var rgba:int = int("0x"+rgb.toString(16) + a.toString(16));) takes 851 ms
using bitwise ops (var rgba:uint = rgb << 8| a;) takes 3 ms
As you can the bitwise version is much faster and for your case even less verbose than the string version. Also, now that you understand bitwise operators probably it's easier to read/understand.
In conclusion:
var color:String = "#0000FF"; //blue
var alpha:Number = 42; //42% or 42/100
var rgb:uint = (uint)(color.replace("#","0x"));
var a:uint = (uint)((alpha * .01) * 255);
var rgba:uint = rgb << 8 | a;
trace("hex: #",rgba.toString(16),"test",0x0000ff6b.toString(16));
Also, it's funny you mentioned Google, because you can use the search to convert to hex.
Update:
There seems to be a bit of confusion so I've split the 3 steps into functions:
converting a hex string to an int
converting a alpha percentage (0-100) to a 0-255 int
concatenating the above
Which would be:
function getHex(hexStr:String):uint{
return (uint)(hexStr.replace("#","0x"));
}
function getHexAlpha(alpha:uint):uint{
return (uint)((alpha * .01) * 255);
}
function rgbaConcat(rgb:uint,a:uint):uint{
return rgb << 8 | a;
}
trace("test",rgbaConcat(getHex("#FF9900"),getHexAlpha(50)).toString(16));
or all in one go:
function rgbaConcat(hexStr:String,alpha:uint):uint{
var rgb:uint = (uint)(hexStr.replace("#","0x"));
var a:uint = (uint)((alpha * .01) * 255);
return (rgb << 8 | a);
}
trace("test",rgbaConcat("#123456",100).toString(16));
I'm not sure if sprintf or something similar is available in action script, but you would use something like:
var alpha_2:int = Math.round(255*alpha/100);
var rgba:String = sprintf("%s%2x", color, alpha_2);
By the way, be sure to check whether it is supposed to be #RRGGBBAA or #AARRGGBB
So apparently sprintf is not available, you can use some substitute as mentioned in Is there something like printf in Action Script 3?
If you do not like to use a printf like function you can use:
function hex_char(value:int) {
if (value < 0)
return "X";
if (value < 10)
return String.fromCharCode("0".charCodeAt(0)+value);
if (value < 16)
return String.fromCharCode("A".charCodeAt(0)+value-10);
return "X";
}
var alpha_2:int = Math.round(255*alpha/100);
var rgba:String = color + hex_char(alpha_2/16) + hex_char(alpha_2%16);
alternatively you coulde use the following definition for hex_char which (I assume) will give you an exception/error for any value under 0 or over 15 instead of "X"
function hex_char(value:int) {
return "0123456789ABCDEF".charAt(value);
}

C++ ROT13 Function Crashes

I'm not too good with C++, however; my code compiled, but the function crashes my program, the below is a short sum-up of the code; it's not complete, however the function and call is there.
void rot13(char *ret, const char *in);
int main()
{
char* str;
MessageBox(NULL, _T("Test 1; Does get here!"), _T("Test 1"), MB_OK);
rot13(str, "uryyb jbeyq!"); // hello world!
/* Do stuff with char* str; */
MessageBox(NULL, _T("Test 2; Doesn't get here!"), _T("Test 2"), MB_OK);
return 0;
}
void rot13(char *ret, const char *in){
for( int i=0; i = sizeof(in); i++ ){
if(in[i] >= 'a' && in[i] <= 'm'){
// Crashes Here;
ret[i] += 13;
}
else if(in[i] > 'n' && in[i] <= 'z'){
// Possibly crashing Here too?
ret[i] -= 13;
}
else if(in[i] > 'A' && in[i] <= 'M'){
// Possibly crashing Here too?
ret[i] += 13;
}
else if(in[i] > 'N' && in[i] <= 'Z'){
// Possibly crashing Here too?
ret[i] -= 13;
}
}
}
The function gets to "Test 1; Does get Here!" - However it doesn't get to "Test 2; Doesn't get here!"
Thank you in advanced.
-Nick Daniels.
str is uninitialised and it is being dereferenced in rot13, causing the crash. Allocate memory for str before passing to rot13() (either on the stack or dynamically):
char str[1024] = ""; /* Large enough to hold string and initialised. */
The for loop inside rot13() is also incorrect (infinte loop):
for( int i=0; i = sizeof(in); i++ ){
change to:
for(size_t i = 0, len = strlen(in); i < len; i++ ){
You've got several problems:
You never allocate memory for your output - you never initialise the variable str. This is what's causing your crash.
Your loop condition always evaluates to true (= assigns and returns the assigned value, == tests for equality).
Your loop condition uses sizeof(in) with the intention of getting the size of the input string, but that will actually give you the size of the pointer. Use strlen instead.
Your algorithm increases or decreases the values in the return string by 13. The values you place in the output string are +/- 13 from the initial values in the output string, when they should be based on the input string.
Your algorithm doesn't handle 'A', 'n' or 'N'.
Your algorithm doesn't handle any non-alphabetic characters, yet the test string you use contains two.

How would you calculate all possible permutations of 0 through N iteratively?

I need to calculate permutations iteratively. The method signature looks like:
int[][] permute(int n)
For n = 3 for example, the return value would be:
[[0,1,2],
[0,2,1],
[1,0,2],
[1,2,0],
[2,0,1],
[2,1,0]]
How would you go about doing this iteratively in the most efficient way possible? I can do this recursively, but I'm interested in seeing lots of alternate ways to doing it iteratively.
see QuickPerm algorithm, it's iterative : http://www.quickperm.org/
Edit:
Rewritten in Ruby for clarity:
def permute_map(n)
results = []
a, p = (0...n).to_a, [0] * n
i, j = 0, 0
i = 1
results << yield(a)
while i < n
if p[i] < i
j = i % 2 * p[i] # If i is odd, then j = p[i], else j = 0
a[j], a[i] = a[i], a[j] # Swap
results << yield(a)
p[i] += 1
i = 1
else
p[i] = 0
i += 1
end
end
return results
end
The algorithm for stepping from one permutation to the next is very similar to elementary school addition - when an overflow occurs, "carry the one".
Here's an implementation I wrote in C:
#include <stdio.h>
//Convenience macro. Its function should be obvious.
#define swap(a,b) do { \
typeof(a) __tmp = (a); \
(a) = (b); \
(b) = __tmp; \
} while(0)
void perm_start(unsigned int n[], unsigned int count) {
unsigned int i;
for (i=0; i<count; i++)
n[i] = i;
}
//Returns 0 on wraparound
int perm_next(unsigned int n[], unsigned int count) {
unsigned int tail, i, j;
if (count <= 1)
return 0;
/* Find all terms at the end that are in reverse order.
Example: 0 3 (5 4 2 1) (i becomes 2) */
for (i=count-1; i>0 && n[i-1] >= n[i]; i--);
tail = i;
if (tail > 0) {
/* Find the last item from the tail set greater than
the last item from the head set, and swap them.
Example: 0 3* (5 4* 2 1)
Becomes: 0 4* (5 3* 2 1) */
for (j=count-1; j>tail && n[j] <= n[tail-1]; j--);
swap(n[tail-1], n[j]);
}
/* Reverse the tail set's order */
for (i=tail, j=count-1; i<j; i++, j--)
swap(n[i], n[j]);
/* If the entire list was in reverse order, tail will be zero. */
return (tail != 0);
}
int main(void)
{
#define N 3
unsigned int perm[N];
perm_start(perm, N);
do {
int i;
for (i = 0; i < N; i++)
printf("%d ", perm[i]);
printf("\n");
} while (perm_next(perm, N));
return 0;
}
Is using 1.9's Array#permutation an option?
>> a = [0,1,2].permutation(3).to_a
=> [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
Below is my generics version of the next permutation algorithm in C# closely resembling the STL's next_permutation function (but it doesn't reverse the collection if it is the max possible permutation already, like the C++ version does)
In theory it should work with any IList<> of IComparables.
static bool NextPermutation<T>(IList<T> a) where T: IComparable
{
if (a.Count < 2) return false;
var k = a.Count-2;
while (k >= 0 && a[k].CompareTo( a[k+1]) >=0) k--;
if(k<0)return false;
var l = a.Count - 1;
while (l > k && a[l].CompareTo(a[k]) <= 0) l--;
var tmp = a[k];
a[k] = a[l];
a[l] = tmp;
var i = k + 1;
var j = a.Count - 1;
while(i<j)
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
i++;
j--;
}
return true;
}
And the demo/test code:
var src = "1234".ToCharArray();
do
{
Console.WriteLine(src);
}
while (NextPermutation(src));
I also came across the QuickPerm algorithm referenced in another answer. I wanted to share this answer in addition, because I saw some immediate changes one can make to write it shorter. For example, if the index array "p" is initialized slightly differently, it saves having to return the first permutation before the loop. Also, all those while-loops and if's took up a lot more room.
void permute(char* s, size_t l) {
int* p = new int[l];
for (int i = 0; i < l; i++) p[i] = i;
for (size_t i = 0; i < l; printf("%s\n", s)) {
std::swap(s[i], s[i % 2 * --p[i]]);
for (i = 1; p[i] == 0; i++) p[i] = i;
}
}
I found Joey Adams' version to be the most readable, but I couldn't port it directly to C# because of how C# handles the scoping of for-loop variables. Hence, this is a slightly tweaked version of his code:
/// <summary>
/// Performs an in-place permutation of <paramref name="values"/>, and returns if there
/// are any more permutations remaining.
/// </summary>
private static bool NextPermutation(int[] values)
{
if (values.Length == 0)
throw new ArgumentException("Cannot permutate an empty collection.");
//Find all terms at the end that are in reverse order.
// Example: 0 3 (5 4 2 1) (i becomes 2)
int tail = values.Length - 1;
while(tail > 0 && values[tail - 1] >= values[tail])
tail--;
if (tail > 0)
{
//Find the last item from the tail set greater than the last item from the head
//set, and swap them.
// Example: 0 3* (5 4* 2 1)
// Becomes: 0 4* (5 3* 2 1)
int index = values.Length - 1;
while (index > tail && values[index] <= values[tail - 1])
index--;
Swap(ref values[tail - 1], ref values[index]);
}
//Reverse the tail set's order.
int limit = (values.Length - tail) / 2;
for (int index = 0; index < limit; index++)
Swap(ref values[tail + index], ref values[values.Length - 1 - index]);
//If the entire list was in reverse order, tail will be zero.
return (tail != 0);
}
private static void Swap<T>(ref T left, ref T right)
{
T temp = left;
left = right;
right = temp;
}
Here's an implementation in C#, as an extension method:
public static IEnumerable<List<T>> Permute<T>(this IList<T> items)
{
var indexes = Enumerable.Range(0, items.Count).ToArray();
yield return indexes.Select(idx => items[idx]).ToList();
var weights = new int[items.Count];
var idxUpper = 1;
while (idxUpper < items.Count)
{
if (weights[idxUpper] < idxUpper)
{
var idxLower = idxUpper % 2 * weights[idxUpper];
var tmp = indexes[idxLower];
indexes[idxLower] = indexes[idxUpper];
indexes[idxUpper] = tmp;
yield return indexes.Select(idx => items[idx]).ToList();
weights[idxUpper]++;
idxUpper = 1;
}
else
{
weights[idxUpper] = 0;
idxUpper++;
}
}
}
And a unit test:
[TestMethod]
public void Permute()
{
var ints = new[] { 1, 2, 3 };
var orderings = ints.Permute().ToList();
Assert.AreEqual(6, orderings.Count);
AssertUtil.SequencesAreEqual(new[] { 1, 2, 3 }, orderings[0]);
AssertUtil.SequencesAreEqual(new[] { 2, 1, 3 }, orderings[1]);
AssertUtil.SequencesAreEqual(new[] { 3, 1, 2 }, orderings[2]);
AssertUtil.SequencesAreEqual(new[] { 1, 3, 2 }, orderings[3]);
AssertUtil.SequencesAreEqual(new[] { 2, 3, 1 }, orderings[4]);
AssertUtil.SequencesAreEqual(new[] { 3, 2, 1 }, orderings[5]);
}
The method AssertUtil.SequencesAreEqual is a custom test helper which can be recreated easily enough.
How about a recursive algorithm you can call iteratively? If you'd actually need that stuff as a list like that (you should clearly inline that rather than allocate a bunch of pointless memory). You could simply calculate the permutation on the fly, by its index.
Much like the permutation is carry-the-one addition re-reversing the tail (rather than reverting to 0), indexing the specific permutation value is finding the digits of a number in base n then n-1 then n-2... through each iteration.
public static <T> boolean permutation(List<T> values, int index) {
return permutation(values, values.size() - 1, index);
}
private static <T> boolean permutation(List<T> values, int n, int index) {
if ((index == 0) || (n == 0)) return (index == 0);
Collections.swap(values, n, n-(index % n));
return permutation(values,n-1,index/n);
}
The boolean returns whether your index value was out of bounds. Namely that it ran out of n values but still had remaining index left over.
And it can't get all the permutations for more than 12 objects.
12! < Integer.MAX_VALUE < 13!
-- But, it's so very very pretty. And if you do a lot of things wrong might be useful.
I have implemented the algorithm in Javascript.
var all = ["a", "b", "c"];
console.log(permute(all));
function permute(a){
var i=1,j, temp = "";
var p = [];
var n = a.length;
var output = [];
output.push(a.slice());
for(var b=0; b <= n; b++){
p[b] = b;
}
while (i < n){
p[i]--;
if(i%2 == 1){
j = p[i];
}
else{
j = 0;
}
temp = a[j];
a[j] = a[i];
a[i] = temp;
i=1;
while (p[i] === 0){
p[i] = i;
i++;
}
output.push(a.slice());
}
return output;
}
I've used the algorithms from here. The page contains a lot of useful information.
Edit: Sorry, those were recursive. uray posted the link to the iterative algorithm in his answer.
I've created a PHP example. Unless you really need to return all of the results, I would only create an iterative class like the following:
<?php
class Permutator implements Iterator
{
private $a, $n, $p, $i, $j, $k;
private $stop;
public function __construct(array $a)
{
$this->a = array_values($a);
$this->n = count($this->a);
}
public function current()
{
return $this->a;
}
public function next()
{
++$this->k;
while ($this->i < $this->n)
{
if ($this->p[$this->i] < $this->i)
{
$this->j = ($this->i % 2) * $this->p[$this->i];
$tmp = $this->a[$this->j];
$this->a[$this->j] = $this->a[$this->i];
$this->a[$this->i] = $tmp;
$this->p[$this->i]++;
$this->i = 1;
return;
}
$this->p[$this->i++] = 0;
}
$this->stop = true;
}
public function key()
{
return $this->k;
}
public function valid()
{
return !$this->stop;
}
public function rewind()
{
if ($this->n) $this->p = array_fill(0, $this->n, 0);
$this->stop = $this->n == 0;
$this->i = 1;
$this->j = 0;
$this->k = 0;
}
}
foreach (new Permutator(array(1,2,3,4,5)) as $permutation)
{
var_dump($permutation);
}
?>
Note that it treats every PHP array as an indexed array.