Does Gray code exist for other bases than two? - math

Just a matter of curiosity, is the Gray code defined for bases other than base two?
I tried to count in base 3, writing consecutive values paying attention to change only one trit at a time. I've been able to enumerate all the values up to 26 (3**3-1) and it seems to work.
000 122 200
001 121 201
002 120 202
012 110 212
011 111 211
010 112 210
020 102 220
021 101 221
022 100 222
The only issue I can see, is that all three trits change when looping back to zero. But this is only true for odd bases. When using even bases looping back to zero would only change a single digit, as in binary.
I even guess it can be extended to other bases, even decimal. This could lead to another ordering when counting in base ten ... :-)
0 1 2 3 4 5 6 7 8 9 19 18 17 16 15 14 13 12 11 10
20 21 22 23 24 25 26 27 28 29 39 38 37 36 35 34 33 32 31 30
Now the question, has anyone ever heard of it? Is there an application for it? Or it is just mathematical frenzy?

Yes. Have a look at the Gray code article at wikipedia. It has a section on n-ary Gray Code.
There are many specialized types of Gray codes other than the binary-reflected Gray code. One such type of Gray code is the n-ary Gray code, also known as a non-Boolean Gray code. As the name implies, this type of Gray code uses non-Boolean values in its encodings.

Just for completeness (as aioobe already gave the right answer), here's a C++ program that lists all the 168 2-digit gray codes for base 3 that start with 00 and marks the 96 cyclic ones. Using the algorithm from Wikipedia, you can construct longer Gray codes easily for even bases. For uneven bases, you can change the program to generate according Gray codes.
The first cyclic 2-digit gray code found with this program is this one:
00 01 02 12 10 11 21 22 20
After changing the program, the first cyclic 3-digit gray found is this:
000 001 002 012 010 011 021 020 022 122 102 100 101 111
110 112 212 202 222 220 120 121 221 201 211 210 200
Code:
#include <stdio.h>
#include <stdlib.h>
// Highest number using two trits
#define MAXN 9
int gray_code_count, cyclic_count;
bool changes_one_trit(int code1, int code2) {
int trits_changed = 0;
if ((code1 / 3) != (code2 / 3)) trits_changed++;
if ((code1 % 3) != (code2 % 3)) trits_changed++;
return (trits_changed == 1);
}
int generate_gray_code(int* code, int depth) {
bool already_used;
if (depth == MAXN) {
for (int i = 0; i < MAXN; i++) {
printf("%i%i ", code[i]/3, code[i]%3);
}
// check if cyclic
if (changes_one_trit(code[MAXN-1], 0)) {
printf("cyclic");
cyclic_count++;
}
printf("\n");
gray_code_count++;
}
// Iterate through the codes that only change one trit
for (int i = 0; i < MAXN; i++) {
// Check if it was used already
already_used = false;
for (int j = 0; j < depth; j++) {
if (code[j] == i) already_used = true;
}
if (already_used) continue;
if (changes_one_trit(code[depth-1], i)) {
code[depth] = i;
generate_gray_code(code, depth + 1);
}
}
}
int main() {
int* code = (int*)malloc(MAXN * sizeof(int));
code[0] = 0;
gray_code_count = 0;
generate_gray_code(code, 1);
printf("%i gray codes found, %i of them are cyclic\n", gray_code_count, cyclic_count);
free(code);
}

Related

How to create a window of arbitrary size in Kusto?

Using prev() function I can access previous rows individually.
mytable
| sort by Time asc
| extend mx = max_of(prev(Value, 1), prev(Value, 2), prev(Value, 3))
How to define a window to aggregate over in more generic way? Say I need maximum of 100 values in previous rows. How to write a query that does not require repeating prev() 100 times?
Can be achieved by combining scan and series_stats_dynamic().
scan is used to create an array of last x values, per record.
series_stats_dynamic() is used to get the max value of each array.
// Data sample generation. Not part of the solution
let mytable = materialize(range i from 1 to 15 step 1 | extend Time = ago(1d*rand()), Value = toint(rand(100)));
// Solution starts here
let window_size = 3; // >1
mytable
| order by Time asc
| scan declare (last_x_vals:dynamic)
with
(
step s1 : true => last_x_vals = array_concat(array_slice(s1.last_x_vals, -window_size + 1, -1), pack_array(Value));
)
| extend toint(series_stats_dynamic(last_x_vals).max)
i
Time
Value
last_x_vals
max
5
2022-06-10T11:25:49.9321294Z
45
[45]
45
14
2022-06-10T11:54:13.3729674Z
82
[45,82]
82
2
2022-06-10T13:25:40.9832745Z
44
[45,82,44]
82
1
2022-06-10T17:38:28.3230397Z
24
[82,44,24]
82
7
2022-06-10T18:29:33.926463Z
17
[44,24,17]
44
15
2022-06-10T19:54:33.8253844Z
9
[24,17,9]
24
3
2022-06-10T20:17:46.1347592Z
43
[17,9,43]
43
12
2022-06-11T00:02:55.5315197Z
94
[9,43,94]
94
9
2022-06-11T00:11:18.5924511Z
61
[43,94,61]
94
11
2022-06-11T00:39:40.6858444Z
38
[94,61,38]
94
4
2022-06-11T03:54:59.418534Z
84
[61,38,84]
84
10
2022-06-11T05:55:38.2904242Z
6
[38,84,6]
84
6
2022-06-11T07:25:43.3977923Z
36
[84,6,36]
84
13
2022-06-11T09:36:08.7904844Z
28
[6,36,28]
36
8
2022-06-11T09:51:45.2225391Z
73
[36,28,73]
73
Fiddle

How to extend a hash with multiple values in R

So I understand that in R, a hash() is similar to a dictionary. I would like to extract specific values from my dataframe and put them in to a hash.
The componentindex column is were I have my keys and the cluster.index + UniqueFileSourceCounts columns contain my values. So for the same key I have multiple values. e.g: hash {91: [1,15],[22,99] etc..
So I would like to create a hash that contains each key, with multiple values. But im not sure how to do that.
mini_df <- head(df,10) #using a small df
compID <- unique(mini_df$componentindex) #list with unique keys
h1 <- hash()
for (i in 1:length(mini_df)){
if(compID == mini_df[i,"componentindex"]){
h1 <- hash(mini_df[i,"componentindex"] ,c(mini_df[i,"cluster.index"],mini_df[i,"UniqueFileSourcesCount"]))
}
#h2 <- append(h2,h1)
}
if I print h1 , I end up having only the last value:
<hash> containing 1 key-value pair(s).
91 : 42 5
Which I understand since I don't append to this hash but overwrite it. Im not sure how to append/expand hashes in R and I have not been able to find a solution yet.
mini_df:
UniqueFileSourcesCount cluster.index componentindex
1 15 1 91
2 15 10 -1
3 99 22 91
4 63 23 1675
5 12 25 91
6 6 27 91
7 50 37 91
8 5 42 91
9 2 43 -1
10 2 69 -1

SQLite Ordering Whole Numbers

I am fairly aware that ORDER BY in SQLite puts the number in Ascending order unless DESC is at the end. But I realized that it only worked for the starting numbers.
i.e
INT
14
78
357
2999
57
888
ORDER BY INT
Gives
14
2999
357
57
78
888
Is it possible to use the ORDER BY function where the whole numbers are in ascending Order?
As such
14
57
78
357
888
2999
select (INT * 1) as "int_number" from mytable order by 1
or as someone points out in the link:
select INT from mytable order by (cast INT as Integer)

How to switch between radians and degrees in SAS

just looking for an easy way to run trig functions in SAS without having to manually correct in each calculation. Below is what I am working with.
I am running this in SAS 9 probably, the SAS Studio Student Module but this is a general SAS question.
I have manually created a variable, 'rad' in the 'calc' data step to deal with this but it adds a step of complexity that I would like to avoid.
I am asking whether there is a system setting, alternate trig function or ... ? that would change the calculation from:
bh_x = cos(rad*bh_a)*bh_l ;
to:
bh_x = cos(bh_a)*bh_l ;
so I don't have to manually convert my angle in degrees to radians for the trig function to work.
Thanks to anyone reading this and putting any mental effort to the solution!
Tim
data spec ;
length
b2h_a 8
b2h_l 8
b2h_l_e 8
bike $ 8
name $ 16
;
input
bike $
name $
bh_a
bh_l
ht_a
spcr
st_h
st_a
st_l
hb_r
hb_a
;
datalines ;
srcn (0,0) 0 0 67 0 0 0 0 0 0
srcn c 41 658 71.5 27 40 25 120 100 13
srcn ne_27_n13 41 658 71.5 27 40 27 127 100 13
srcn ne_15_0 41 658 71.5 15 40 27 127 100 0
srcn ne_5_0 41 658 71.5 5 40 27 127 100 0
srcn ne_2_n9 41 658 71.5 2 40 27 127 100 9
srcn ne_5_10 41 658 71.5 5 40 27 127 100 -10
srcn ne_10_rf10 41 658 71.5 10 40 27 127 20 -10
srcn max 41 658 90 250 0 0 250 0 0
;
run ;
data calc ;
set spec ;
pi=constant('pi') ;
rad=pi/180 ;
bh_x = cos(rad*bh_a)*bh_l ;
bh_y = sin(rad*bh_a)*bh_l ;
sr_x = (cos(rad*ht_a)*(spcr+st_h/2))*-1 ;
sr_y = sin(rad*ht_a)*(spcr+st_h/2);
st_x = cos(rad*(90-ht_a+st_a))*st_l ;
st_y = sin(rad*(90-ht_a+st_a))*st_l ;
hb_x = cos(rad*(90-hb_a))*hb_r*-1 ;
hb_y = sin(rad*(90-hb_a))*hb_r ;
hd_x = bh_x + sr_x + st_x + hb_x ;
hd_y = bh_y + sr_y + st_y + hb_y ;
if hd_x=0 then do ;
b2h_a=0 ;
b2h_l=0 ;
end ;
else do ;
b2h_a = atan(hd_y/hd_x)/rad ;
b2h_l = hd_y/sin(b2h_a*rad) ;
end ;
b2h_l_e = b2h_l/25.4 ;
drop pi rad ;
format
b2h_a 5.
b2h_l 5.
b2h_l_e 5.
bh_a 5.
bh_l 5.
ht_a 5.
spcr 5.
st_h 5.
st_a 5.
st_l 5.
hb_r 5.
hb_a 5.
bh_x 5.
bh_y 5.
sr_x 5.
sr_y 5.
st_x 5.
st_y 5.
hb_x 5.
hb_y 5.
hd_x 5.
hd_y 5.
b2h_a 5.
b2h_l 5.
b2h_l_e 5.1
;
run ;
There are no trig functions in SAS that accept DEGREE or GRADIAN arguments. You always need to convert from your data's angular measurement system to RADIAN.
You can write a macro to perform the conversion. Example:
%macro cosD(theta);
%* theta is angle in degrees;
%* emit data step source code that performs conversion from degrees to radians;
cos(&theta*constant('PI')/180)
%mend;
In use:
data calc ;
set spec ;
bh_x = %cosD(bh_a) * bh_l ;
You could convert the angular data to radians during the step where input occurs and then not have to worry about it again.

Having issues with adding two positions of array

Question in regards to adding arrays. I have this code below:
B[row][col] = B[row+1][col+1] + B[row][col+1];
Let say row = 2, col = 3; I don't quite understand what happens how. We have the (=) assignment so I'm guessing would assign whatever is on the right but I don't know how to count it. In this example it come up to me to be: 13 on the right side but that doesn't make sense. I would assign 13 value to b[row][col] ??? In the tracing program showed as 2. I don't understand, please help!
I'm not entirely sure what it is you're asking but essentially you have a 2D array and the B[row][col] syntax is to access a specific "cell" within the 2D array. Think of it like a grid. So what you're doing with the assignment operator is taking the values in cells B[row+1][col+1] and B[row][col+1], adding them together, and assigning that resulting value to the cell B[row][col]. Does that make sense? Also it'll be good to make sure you don't get any index out of bounds exceptions doing this.
This does somewhat depend on the tool/language you are using, for instance matlab starts indexing arrays at 1 so the first element of an array a is a[1] while languages like C/Java start indexing at 0 so the first element of an array a is a[0].
Lets assume that indexing is done like in C/Java, then consider a multidimensional array B
12 13 14 11
41 17 23 22
18 10 20 38
81 17 32 61
Then with row = 2 and col = 3 you will have that B[row][col] as the element that sits on the third row (remembering indexing starts at 0, so B[2] is the third row) and fourth column, marked here between * signs.
12 13 14 11
41 17 23 22
18 10 20 *38*
81 17 32 61
As for changing a value in the multidimensional array, it is done by assigning a new value to the index of the old value.
B[row][col] = B[row+1][col+1] + B[row][col+1];
With row=1 and col=0 we get
B[1][0] = B[2][1] + B[1][1];
B[1][0] = 10 + 17;
B[0][0] = 27;
Or:
12 13 14 11 12 13 14 11
(41) 17 23 22 (27) 17 23 22
18 10 20 38 ==> 18 10 20 38
81 17 32 61 81 17 32 61

Resources