What algorithm maps number 27 to BBC - c

To clarify the confusion - I want to write a function that maps a number to the following list of letter combinations.
My question is best illustrated with the following table.
A 1
B 2
C 3
AA 4
AB 5
AC 6
BA 7
BB 8
BC 9
CA 10
CB 11
CC 12
AAA 13
AAB 14
AAC 15
ABA 16
ABB 17
ABC 18
ACA 19
ACB 20
ACC 21
BAA 22
BAB 23
BAC 24
BBA 25
BBB 26
BBC 27
I want to design a function that is able to map a given number, to the left column of this here table. I've tried assigning numerals to the letters first.
A = 0
B = 1
C = 2
This allows me form the following table (Cn - Column number, from right to left).
C3 C2 C1 Number
0 1
1 2
2 3
0 0 4
0 1 5
0 2 6
1 0 7
1 1 8
1 2 9
2 0 10
2 1 11
2 2 12
0 0 0 13
0 0 1 14
0 0 2 15
0 1 0 16
0 1 1 17
0 1 2 18
0 2 0 19
0 2 1 20
0 2 2 21
1 0 0 22
1 0 1 23
1 0 2 24
1 1 0 25
1 1 1 26
1 1 2 27
So this looks like an recursive loop type algorithm, but I can't figure out how to put this down in code. Any suggestions?

As whoever the person was (user: n.m.) who wrote the comment that disappeared, this is just base-3 counting, except all numerals are offset by +1. The digits really stand for A=0, B=1, C=2
Hence BBC = ('B'+1)*3^2 + ('B'+1)*3 + ('C'+1) = 2*9 + 2*3 + 3 = 27
The pseudocode for fromInt(), Antoine has already given you it. Same idea:
char* fromInt(int n) {
result = ""
working_val = (n-1)
while (working_val>0) {
Prepend to result the digit "CAB"[ working_val % 3 ]
working_val /= 3
}
return result
}
Strictly we don't care about catching the special-case 0 which Antoine noted, because your list doesn't have a representation for 0.

#include <stdio.h>
#include <string.h>
int toInt(const char *str, int acc) {
if(*str)
return toInt(++str, acc * 3 + *str - 'A' + 1);
else
return acc;
}
char *fromInt(int n, char *outbuff){
char* p = outbuff;
while(n){
*p++ = 'A' + ((n % 3 == 0)? 3 : n % 3) - 1;
n = (n - 1) / 3;
}
*p = '\0';
return strrev(outbuff);//strrev isn't ANSI C
}
int main(void) {
char buff[] = "BBC";
int x = toInt(buff, 0);
printf("%d\n", x);
printf("%s\n", fromInt(x, buff));
return 0;
}

This is a kind of base-3 system, but the digits are 1 (A), 2 (B) and 3 (C), there is no 0.
The conversion formula from this representation is, as usual,
3^n*a_n + 3^(n-1)*a_{n-1} + ... + 3^0*a_0
The reverse conversion is just like a regular conversion to base 3, the only difference is that a modified remainder function is used:
int modified_remainder(m, n)
{
int answer = m % n;
if (answer == 0) answer = n;
return answer;
}
Now given the number m, the last digit of its representation would be
a_0 = modified_remainder(m, 3)
The one before last is
m_1 = (m - a_0) / 3; // m-a_0 is always divisible by 3
a_1 = modified_remainder(m_1, 3)
The next one is
m_2 = (m_1 - a_1) / 3
a_2 = modified_remainder(m_2, 3)
and so on. You stop when m_k < n.
Try to verify these claims, it's a good exercise.

Related

AWK array seems to empty itself?

I am trying to learn awk by solving code puzzles. I am trying to read several "grids" of integers (representing bingo boards as per https://adventofcode.com/2021/day/4) into a three-dimensional awk array. An example "grid" can look like this:
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
And there are several of these in a longer input file. After reading each line into an array rows I am attempting to organize the numbers into this multi dimensional array called boards. Here is my example code:
{
b = 0
for (i in rows) {
split(rows[i], nums, " ")
for (j in nums) {
r = i % 5
n = j - 1
boards[b][r][n] = nums[j]
print b, r, n, nums[j], boards[b][r][n]
}
if (i%5==0)
++b
}
print boards[0][1][1]
}
Notice the debug printout print b, r, n, nums[j], boards[b][r][n] which indeed outputs the correct values for boards[b][r][n] on that row:
0 0 0 22 22
0 0 1 13 13
0 0 2 17 17
Etc. This seems to verify that the multi dimensional array gets written properly. Yet on the final line of the example code, the output is instead empty. I have tried using the form boards[b, r, n] for the array as well with the exact same result. Obviously there's something I'm not quite understanding here. Any help is appreciated. Full code for reproducibility:
# === ex.txt ===
7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7
# === solve.awk ===
BEGIN {
r = 0
}
{
if (NR == 1)
split($0, draws, "")
else if (NR != 2 && (NR-3)%6 != 5)
rows[r++] = $0
}
END {
b = 0
for (i in rows) {
split(rows[i], nums, " ")
for (j in nums) {
r = i % 5
n = j - 1
boards[b][r][n] = nums[j]
print b, r, n, nums[j], boards[b][r][n]
}
if (i%5==0)
++b
}
print boards[0][1][1]
}
I run this with awk -f solve.awk ex.txt. awk --version outputs GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0-p13, GNU MP 6.2.1) as its first line. Thank you!
You are incrementing b at the end of the first iteration of your for (i in rows) loop because i == 0 ==> i%5 == 0, while you want to do it at the end of the 5th iteration. Try if (i%5 == 4) ++b.
Note that as you use GNU awk you could simplify all this. When the record separator (RS) is the empty string the records are separated by empty lines (one record per board):
$ awk -v RS='' '
NR>1 {
a[NR-2][1]; split($0, a[NR-2]);
}
END {
for(b in a) for(r in a[b])
boards[b][int((r-1)/5)][(r-1)%5] = a[b][r];
for(b in boards) for(r in boards[b]) for(n in boards[b][r])
print b, r, n, boards[b][r][n]
}' ex.txt
0 0 0 22
0 0 1 13
0 0 2 17
0 0 3 11
0 0 4 0
0 1 0 8
...

Compute recursion for one column conditionally on values in another columns

I was given dataset named Temp.dat with 2 columns (Dataset here). I initially formed structure named structure data_t data[100] so that I could arrange the columns in an increasing order based on the first column (Column 0 = min(failure time, censored time), Column 1 indicates 1 = Death observation, 0 = censored observation). A portion of the structured dataset has the following form
0.064295 1
0.070548 1
0.070850 1
0.071508 0
0.077981 1
0.086628 1
0.088239 1
0.090754 1
0.093260 0
0.094090 1
0.094367 1
0.097019 1
0.099336 1
0.103765 1
0.103961 1
0.111674 0
0.122609 0
0.123730 1
Now, I want to write the C code to form different time periods whose endpoints always end with entry 1in the 2nd column. Looks like the following:
Expected output - 3rd column (Time Interval) added
0.064295 1 [0 0.064295)
0.070548 1 [0.064295 0.070548)
0.070850 1 [0.070548 0.070850)
0.071508 0 [0.070850 0.077891) ---> Skip 0.071508 here because of 0 in column 1
0.077981 1 [0.070850 0.077981)
0.086628 1 [0.077981 0.086628)
0.088239 1 [0.086628 0.088239)
0.090754 1 [0.088239 0.090754)
0.093260 0 [0.090754 0.094090)
0.094090 1 [0.090754 0.094090)
0.094367 1 [0.094090 0.094367)
0.097019 1 [0.094367 0.097019)
0.099336 1 [0.097019 0.099336)
0.103765 1 [0.099336 0.103765)
0.103961 1 [0.103765 0.103961)
0.111674 0 [0.103961 0.123730)
0.122609 0 [0.103961 0.123730)
0.123730 1 [0.103961 0.123730)
So far, I am unable to write the code to perform this. So if anyone could help on this step, I would sincerely appreciate it.
Next, I wrote up the following code to get the output shown below. Note that column 2 is not what I want, but this is the best thing so far I could get.
double array[8][MAX];
double total = 100;
for(int i = 0; i < MAX; i++) {
double start = 0;
double count = 0;
if(i) start = data[i - 1].x;
array[0][i] = data[i].x;
array[1][i] = data[i].y;
array[2][i] = start;
array[3][i] = data[i].x;
array[4][0] = count;
array[5][0] = count;
array[6][0] = total;
array[7][0] = 1;
/*keep track of number of deaths and censors at each time t_i*/
if (fmod(arr[1][i], 2.0) == 1)
{arr[4][i+1] = count + 1.0;
arr[5][i+1] = count;
}
else {arr[4][i+1] = count;
arr[5][i+1] = count + 1.0;
}
return(0);
}
Sample Output
0.064295 1 [0.060493 0.064295) 1.000000 0.000000 191.000000 0.950000
0.070548 1 [0.064295 0.070548) 1.000000 0.000000 190.000000 0.945000
0.070850 1 [0.070548 0.070850) 1.000000 0.000000 189.000000 0.940000
0.071508 0 [0.070850 0.071508) 1.000000 0.000000 188.000000 0.940000
0.077981 1 [0.071508 0.077981) 0.000000 1.000000 187.000000 0.935000
0.086628 1 [0.077981 0.086628) 1.000000 0.000000 186.000000 0.929973
0.088239 1 [0.086628 0.088239) 1.000000 0.000000 185.000000 0.924946
0.090754 1 [0.088239 0.090754) 1.000000 0.000000 184.000000 0.919919
0.093260 0 [0.090754 0.093260) 1.000000 0.000000 183.000000 0.919919
Column 7 stands for KM estimator of survival distribution function. It was computed based on the following rules:
1. If the i-th entry in column 1 is 0, simply save the corresponding i-th entry in column 6 equal to the previous (i-1)th- entry in the same column.
2. If the i-th entry in column 1 is 1 but one or multiple successive entries before it is 0 (for example, the last entry of column 1 is followed right before by two 0s), we compute the corresponding i-th entry in column 6 with the formula: (i-1)-th entry*(1- 1/(j-th entry in column 5)) where the j-th entry in column 5 corresponds to the nearest entry 1 in column 1 (for example, the last 4 rows of column 1 has 1 0 0 1 in it, which implies the last entry in column 6 would be computed as 0.890096*(1-1/177) where 177 = the first entry in column 5 which has the corresponding entry in column 1 = 1 (rather than 0).
Task left to finish: First, I need to form the right column 2 so that for a random input t in the range of column 0, the code would give the corresponding result in column 6.
Second, I want to compute the variance of KM estimator, using this formula: S(t)^2*(summation over t_i <= t) d_i/(r_i*(r_i-d_i)),
where S(t) = the KM estimator computed at time t (column 7 above), d_i is the total number of deaths up to index i (so, sum of entries up to d_i of column 5 above), r_i = i-th entry in column 6. For example, if t = 0.071, then t_i only has 3 possible values based on Column 0 (t_i would be 0.064295, 0.070548 and 0.070850). I came up with the following working code (not sure if the output was the correct ones)
N = [an integer]; #define size of array here
double sigma[N];
sigma[0] = 0;
double sum[N];
sum[0] = 0;
for(int i=1; i< N; i++){
sum[i] = sum[i-1] + (float)(arr[4][i]/(arr[6][i-1]*(arr[6][i])));
sigma[i] = pow(arr[7][i],2)*sum[i];
printf("%.0lf", sigma[i]);
}
Sample Output
0.004775
0.004750
0.004725
0.004700
0.004675
0.004700
0.004650
0.004625
0.004600
0.004575
0.004600
0.004550
0.004525
0.004500
0.004475
0.004450
0.004425
0.004450
0.004450
0.004400
0.004375
0.004350
0.004325
0.004300
0.004275
0.004250
0.004225
0.004200
0.004175
0.004149
0.004124
0.004150
0.004099
0.004074
0.004100
0.004049
0.004024
0.004051
0.003999
0.003974
0.004001
0.003949
0.003976
0.003923
0.003898
0.003926
0.003873
0.003848
0.003823
0.003797
0.003772
0.003747
0.003775
0.003722
0.003750
0.003696
0.003725
0.003671
0.003700
0.003646
0.003676
0.003621
0.003595
0.003570
0.003544
0.003519
0.003549
0.003494
This is a partial answer. First, lets declare the array as arr[MAX][8], that means you have MAX rows and 8 columns. This makes it easier to sort the data.
Next, lets create dummy data 0.100, 0.101, ... that's easier to look at it.
To find the 5th column, you can use an additional loop (for(int j = i; j < count; j++){...}) to find the next non-zero value.
We have to keep track of total dead counts (dead_count) and increment each time arr[i][1] is zero.
Kaplan-Meier formula is taken as 1 - (double)dead_count/(double)count
MCVE would look like:
#include <stdlib.h>
#include <stdio.h>
int compare_2d_array(const void *pa, const void *pb)
{
double a = *(double*)pa;
double b = *(double*)pb;
if(a > b) return 1;
if(a < b) return -1;
return 0;
}
int main(void)
{
double arr[][8] =
{
{ 0.100, 1, 0, 0, 0, 0, 0 , 0 }, //initialize columns
{ 0.101, 1 }, // we can skip adding the zeros, it's done automatically
{ 0.102, 1 },
{ 0.103, 0 },
{ 0.104, 1 },
{ 0.105, 1 },
{ 0.106, 1 },
{ 0.107, 1 },
{ 0.108, 0 },
{ 0.109, 1 },
{ 0.110, 1 },
{ 0.111, 1 },
{ 0.112, 1 },
{ 0.113, 1 },
{ 0.114, 1 },
{ 0.115, 0 },
{ 0.116, 0 },
{ 0.117, 1 },
};
int count = sizeof(arr)/sizeof(*arr);
//sort
qsort(arr, count, sizeof(arr[0]), compare_2d_array);
int dead_count = 0;
for(int i = 0; i < count; i++)
{
double start = i ? arr[i - 1][0] : 0;
double end = arr[i][0]; //<- I don't know what to use as default value!
//if arr[i][1] is zero, then end should equal the next non-zero value
double end;
for(int j = i; j < count; j++)
{
end = arr[j][0];
if(arr[j][1])
break;
}
arr[i][2] = start;
arr[i][3] = end;
arr[i][4] = arr[i][1];
arr[i][5] = !arr[i][1];
if(!arr[i][1])
dead_count++;
printf("%3d %.6lf %.0lf [%.6lf %.6lf) %.0lf %.0lf %3d %.6lf\n",
i,
arr[i][0],
arr[i][1],
start,
end,
arr[i][4],
arr[i][5],
count - i, 1 - (double)dead_count/(double)count );
}
return 0;
}
Output:
0 0.100000 1 [0.000000 0.100000) 1 0 18 1.000000
1 0.101000 1 [0.100000 0.101000) 1 0 17 1.000000
2 0.102000 1 [0.101000 0.102000) 1 0 16 1.000000
3 0.103000 0 [0.102000 0.104000) 0 1 15 0.944444
4 0.104000 1 [0.103000 0.104000) 1 0 14 0.944444
5 0.105000 1 [0.104000 0.105000) 1 0 13 0.944444
6 0.106000 1 [0.105000 0.106000) 1 0 12 0.944444
7 0.107000 1 [0.106000 0.107000) 1 0 11 0.944444
8 0.108000 0 [0.107000 0.109000) 0 1 10 0.888889
9 0.109000 1 [0.108000 0.109000) 1 0 9 0.888889
10 0.110000 1 [0.109000 0.110000) 1 0 8 0.888889
11 0.111000 1 [0.110000 0.111000) 1 0 7 0.888889
12 0.112000 1 [0.111000 0.112000) 1 0 6 0.888889
13 0.113000 1 [0.112000 0.113000) 1 0 5 0.888889
14 0.114000 1 [0.113000 0.114000) 1 0 4 0.888889
15 0.115000 0 [0.114000 0.117000) 0 1 3 0.833333
16 0.116000 0 [0.115000 0.117000) 0 1 2 0.777778
17 0.117000 1 [0.116000 0.117000) 1 0 1 0.777778

Finding the position of all sets of consecutive ones in an Array (MATLAB)

I have an array of the following values:
X=[1 1 1 2 3 4 1 1 1 1 5 4 2 1 1 2 3 4 1 1 1 1 1 2 2 1]
I want to get the position (the index) of all the consecutive ones in the array, and construct an array that holds the start and end positions of each set of the consecutive zeros:
idx= [1 3; 7 10; 14 15; 19 23; 26 26];
I tried to use the following functions, but I am not sure how to implement it:
positionofoness= find(X==1);
find(diff(X==1));
How can I construct idx array ??
You were almost there with your find and diff solution. To find all the positions where X changes from 1, pad X with a NaN in the beginning and the end:
tmp = find(diff([NaN X NaN] == 1)) % NaN to identify 1st and last elements as start and end
tmp =
1 4 7 11 14 16 19 24 26 27
%start|end start|end
Notice that every even element tmp indicates the index + 1 of where consecutive 1s end.
idx = [reshape(tmp,2,[])]'; % reshape in desired form
idx = [idx(:,1) idx(:,2)-1]; % subtract 1 from second column

How do you create an outer loop to read two separate mazes using the user's input C program

So we're supposed to read an input file from the user.
The input file contains the following:
First Line: The number of mazes in the file
Second Line: the first number is the number of nodes and the second number is the...
ith Line: There will be lines that has the same format as the second line.
These lines serve to tell you that you have reached the next maze. There are n such pairs of numbers, where n is the number indicated in the first line of the file.
The Rest of the Lines: The rest of the lines are sets of three numbers containing the source, number of edges,destination, and edge/path cost.
The problem is, my program only reads the first half of the program. When it comes to the next "maze", it stops.
How to read both mazes in one go? Help please.
Here is the input file:
2
16 15
0 1 1
1 5 1
5 6 1
6 7 1
7 11 1
11 10 1
10 14 1
14 13 1
13 9 1
14 15 1
1 2 1
2 3 1
0 4 1
4 8 1
8 12 1
16 15
0 1 1
1 2 1
2 6 1
6 7 1
7 11 1
11 15 1
15 14 1
14 13 1
13 9 1
9 5 1
9 10 1
2 3 1
0 4 1
4 8 1
8 12 1
And here's my program:
fh = fopen("maze_test_small", "r");
chk_null_ptr(fh);
fscanf(fh, "%d",&nlines);
fscanf(fh, "%d %d", &nnodes, &nedges);
adjlist = (edgelist_t**) calloc(nnodes + 1, sizeof(edgelist_t *));
chk_null_ptr(adjlist);
for(i = 0; i < nnodes; i++)
{
adjlist[i] = (edgelist_t *) calloc(1, sizeof(edgelist_t));
chk_null_ptr(adjlist[i]);
adjlist[i][0].cost = 0;
}
while(nedges--)
{
fscanf(fh, "%d %d %d", &na, &nb, &wt);
adjlist[na] = (edgelist_t *) realloc(adjlist[na], (adjlist[na] [0].cost + 2) * sizeof(edgelist_t));
adjlist[nb] = (edgelist_t *) realloc(adjlist[nb], (adjlist[na][0].cost + 2) * sizeof(edgelist_t));
chk_null_ptr(adjlist[na]);
chk_null_ptr(adjlist[nb]);
adjlist[na][adjlist[na][0].cost + 1].dest = nb;
adjlist[nb][adjlist[nb][0].cost + 1].dest = na;
adjlist[na][adjlist[na][0].cost + 1].cost = wt;
adjlist[nb][adjlist[nb][0].cost + 1].cost = wt;
adjlist[na][0].cost++;
adjlist[nb][0].cost++;
}
You have not used a outer loop with nlines. That's why it is only reading a single maze.
You can do following thing:
for(i = 0; i < nlines; i++){
// your code.
}
and if you do not need nlines anywhere else then,
while(nlines--){
//your code
}

Deleting elements from array in Matlab

Given,
a = [2 4 6 8 10 0 7 18 9 0 8 2 0 5];
b = [1 3 0 5 70 8 6 87 1 9 7 8 0 2];
I am trying to delete elements (in both 'a' & 'b') that corresponds
to '0' or less than '0' in either 'a' or 'b' i.e., I want
% a = [2 4 8 10 7 18 9 8 2 5];
% b = [1 3 5 70 6 87 1 7 8 2];
I am trying like this -
n = length(b);
a1 = [];
b1 = [];
for k = 1:n
if a(n) <= 0 || b(n) <= 0
a1 = [a; a(a > 0)] % eliminates 0 from a
b1 = [b; b(b > 0)] % eliminates 0 from b
end
end
Any help will be very helpful.
Use find:
a = [2 4 6 8 10 0 7 18 9 0 8 2 0 5];
b = [1 3 0 5 70 8 6 87 1 9 7 8 0 2];
A = a( find( a > 0 & b > 0 ) );
B = b( find( a > 0 & b > 0 ) );
or even faster:
C = a( a > 0 & b > 0 );
D = b( a > 0 & b > 0 );
returns:
C =
2 4 8 10 7 18 9 8 2 5
D =
1 3 5 70 6 87 1 7 8 2
If you can be sure, that there are no values below zero you could also use:
E = a( logical(a) & logical(b) );
F = b( logical(a) & logical(b) );
which is a little faster, but containing also negative values.
The efficient and compact way to do this is to first create the relevant index, that prevents double calculation:
idx = a>0 & b>0
a = a(idx);
b = b(idx);

Resources