I am trying to write the old painter game, where you paint around squares and when the perimeter is done the square changes colour, using ncurses. I have written a simple level editor that lets me draw the squares using an asterisk. I have a block structure and an array of them and can create the blocks by brute-force scanning the screen for asterisks and setting blocks to those locations. So I realised that each block is joined to 2 - 4 other blocks, so I could just have pointers to next up/dn/lt/rt blocks and follow the pointers. This would save time because I wouldn't have to check for boundary conditions or that the player stayed on the line, i could simply check if the ptr was null and if so not let the player move in that direction. So I can save the block array and load it into the painter game and it displays it all correctly. I have a ptr to the current block cur_blk which I have set to point to array element 5, and this works. If I gdb, I can print out the value of *cur_blk and it shows everthing is right, but the pointers don't work. I think the problem is in the level editor, but I am stuck.
Here is some code. This is the block struct:
struct block{
int id;
int row, col;
int alive;
struct block *next_up, *next_dn, *next_lt, *next_rt;
struct square *my_squares;
};
Here is the block array setup:
struct block *bp;
int cnt = 0;
for(bp = &the_blocks[0]; bp < &the_blocks[1024]; bp++){
bp->id = cnt;
bp->row = 0;
bp->col = 0;
bp->alive = FALSE;
bp->next_up = NULL;
bp->next_dn = NULL;
bp->next_lt = NULL;
bp->next_rt = NULL;
bp->my_squares = (struct square *)malloc(sizeof(struct square)*4);
cnt++;
}
here is the code to give the blocks the correct co-ords, and link them together - the linky code is in the for(d=0;d<blk_cnt;d++) loop. It rescans the array comparing co-ords, such that if the row is one less and the col is the same then that is set to the_blocks[c].next_up. I am pretty sure this is where the error is but I don't know what it is.
char cc, dn_ch, rt_ch; // cur/next chars
int row, col;
//create blocks
for(row=0;row<24;row++){
for(col=0;col<61;col++){
cc = mvinch(row,col);
if(cc == '*'){
the_blocks[blk_cnt].row = row;
the_blocks[blk_cnt].col = col;
the_blocks[blk_cnt].alive = TRUE;
blk_cnt++;
}
if(row<24) ;
dn_ch = mvinch(row+1, col);
if(col<60) ;
rt_ch = mvinch(row,col+1);
if(cc == '*' && dn_ch == '*' && rt_ch == '*')
make_square(row,col);
}
}
//make into squares and link blocks
int c,d,e, scnt;
for(c=0;c<blk_cnt;c++){
int row = the_blocks[c].row;
int col = the_blocks[c].col;
for(e=0;e<sq_cnt;e++){
// for each square, check top/base then left side and rigth side.
// use tlx, tly etc
scnt = 0;
int tlx = the_squares[e].tlx;
int tly = the_squares[e].tly;
int blx = the_squares[e].blx;
int bly = the_squares[e].bly;
int trx = the_squares[e].trx;
int try = the_squares[e].try;
int brx = the_squares[e].brx;
int bry = the_squares[e].bry;
if(row == tly && col >=tlx && col <= trx){
the_blocks[c].my_squares[scnt] = the_squares[e];
scnt++;
}
if(row == bly && col >=blx && col <= brx){
the_blocks[c].my_squares[scnt] = the_squares[e];
scnt++;
}
if(col == tlx && row >=tly && row <= bly){
the_blocks[c].my_squares[scnt] = the_squares[e];
scnt++;
}
if(col == trx && row >=try && row <= bry){
the_blocks[c].my_squares[scnt] = the_squares[e];
scnt++;
}
}
for(d=0;d<blk_cnt;d++){
if((the_blocks[d].row == row-1) && (the_blocks[d].col == col)){
//the_blocks[c].next_up = (struct block *)malloc(sizeof(struct block));
the_blocks[c].next_up = &the_blocks[d];
}
if((the_blocks[d].row == row+1) && (the_blocks[d].col == col)){
//the_blocks[c].next_dn = (struct block *)malloc(sizeof(struct block));
the_blocks[c].next_dn = &the_blocks[d];
}
if(( the_blocks[d].col == col-1) && (the_blocks[d].row == row)){
//the_blocks[c].next_lt = (struct block )malloc(sizeof(struct block));
the_blocks[c].next_lt = &the_blocks[d];
}
if((the_blocks[d].col == col+1) && (the_blocks[d].row == row)){
//the_blocks[c].next_rt = (struct block *)malloc(sizeof(struct block));
the_blocks[c].next_rt = &the_blocks[d];
}
}
}
Here is the code from the painter game that sets the cur_blk pointer
cur_blk = &the_blocks[5];
move(cur_blk->row, cur_blk->col);
addch('#');
refresh();
and this is the move code, where I thought I could just follow the pointers:
switch(dir){
case UP : if(cur_blk->next_up != NULL){
cur_blk = cur_blk->next_up;
moved = TRUE;
break;
}
case DOWN : if(cur_blk->next_dn != NULL){
cur_blk = cur_blk->next_dn;
moved = TRUE;
break;
}
case LEFT : if(cur_blk->next_lt != NULL){
cur_blk = cur_blk->next_lt;
moved = TRUE;
break;
}
case RIGHT : if(cur_blk->next_rt != NULL){
cur_blk = cur_blk->next_rt;
moved = TRUE;
break;
}
}
I am so stuck it is unreal. Thanks in advance for any help. I can post more code if needed. The level editor works apart from the linky bit!
Related
I have to make my lab))
In general, I should find the index of three students with the smallest rating points.
How I can do it without three loops? Just by one.
In this function, I use structures and output arguments.
int addDelateThree(stud** pListHead, int* Imin, int* Jmin, int* Cmin) {
stud* pTemp = pListHead;
stud* SpTemp = pListHead;
stud* TpTemp = pListHead;
int check = 0;
double min1 = pTemp->madian;
double min2 = SpTemp->madian;
double min3 = pTemp->median;
int i = 0;
while (pTemp != NULL) {
if (min1 > pTemp->madian) {
min1 = pTemp->madian;
*Imin = i;
}
i++;
pTemp = pTemp->next;
}
i = 0;
while (SpTemp != NULL) {
if (min2 > SpTemp->madian && i != *Imin) {
min2 = SpTemp->madian;
*Jmin = i;
}
i++;
SpTemp = SpTemp->next;
}
i = 0;
while (TpTemp != NULL) {
if (min3 > TpTemp->madian && i != *Imin && i != *Jmin) {
min3 = TpTemp->madian;
*Cmin = i;
}
i++;
TpTemp = TpTemp->next;
}
}
Make a list of 3 stud *. Initialize all to point to a dummy record whose .madian = INFINTY;
Walk the linked list once.
Compare node's .madian to list[2]->madian. If <=, adjust list of 3 with new minimal .madian. This may involve several compares as code compares 1st the greatest min value, then next greatest min and finally the least value.
Report result.
O(n) solution.
I have a program that receives in input a large number of values and has to keep track of the n largest received. For example, let's say n is 3 and the input is 1,6,3,5,2 the output would have to be 6,5,3 (not necessarily in this order).
At the moment I'm using a min heap implemented via an array, but that isn't quite cutting it time-wise. Are there any alternatives I can look into?
The "(not necessarily in this order)" implies that you can have a sorted numerically output. As you only have to track values greater or equal than n, with a very large input of integer values, a wise way would be then to keep track of integer ranges instead of values.
It will heavily depend of the inputs. For hughes word integer inputs with a discrete uniform distribution, it would cost less memory and would be faster.
A simple pseudo code implementation would require for each input value to check it against a min heap ordered stack of ranges :
Range is
min as integer
max as integer
next as Range
duplicates as stack of integer
Range(pMin, pMax, pNext)
self.min = pMin
self.max = pMax
self.next = pNext
self.duplicates = empty stack of integer
Range heap_top = NULL
Range current_range = NULL
Range previous_range = NULL
boolean merge_flag
integer value
While read value from input
if value >= n Then
current_range = heap_top
previous_range = NULL
merge_flag = false
While current_range is not null
If value is current_range.min - 1 Then
current_range.min = value
merge_flag = true
Break
End If
If value is current_range.max + 1 Then
current_range.max = value
merge_flag = true
Break
End If
If value < current_range.min Then
current_range = NULL
Break
End If
If value is between current_range.min and current_range.max Then
# Here we track duplicates value
current_range.duplicates.push value
Break
End If
previous_range = current_range
current_range = current_range->next
End While
If current_range is not NULL Then
If merge_flag is true Then
If previous_range is not NULL and current_range.min - 1 is previous_range.max Then
# merge current range into previous one
previous_range.max = current_range.max
# Here we track duplicates value
previous_range.duplicates.pushall current_range.duplicates
previous_range.next = current_range.next
drop current_range
# If we need to keep a track of the range where belong the value
# current_range = previous_range
Else
If current_range.next is not NULL and current_range.max + 1 is
current_range.next.min Then
# merge next range into current one
# We use previous_range to point the next range
previous_range = current_range.next
current_range.max = previous_range.max
# Here we track duplicates value
current_range.duplicates.pushall previous_range.duplicates
current_range.next = previous_range.next
drop previous_range
End If
End If
End If
Else
If previous_range is NULL Then
current_range = new Range(value, value, heap_top)
heap_top = current_range
Else
current_range = new Range(value, value, previous_range.next)
previous_range.next = current_range
End If
End If
End If
End While
Less nodes implies less node traversal processing on the long run if the input is uniformly distributed. Less node traversal processing for each input value to process means a faster global processing, as we have then an algorithm approaching O(N) instead of O(N!) with N as the number of input values.
An example of C implementation of the the previous algorithm :
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
struct s_range {
unsigned int min;
unsigned int max;
struct s_range *next;
unsigned int *duplicates;
unsigned int duplicates_count;
};
struct s_range *new_range(unsigned int pMin,unsigned int pMax, struct s_range *pNext) {
struct s_range *lRange = malloc(sizeof(struct s_range));
if (lRange == NULL) {
perror("new_range: Failed to allocate");
return NULL;
}
lRange->min = pMin;
lRange->max = pMax;
lRange->next = pNext;
lRange->duplicates = NULL;
lRange->duplicates_count = 0;
return lRange;
}
void drop_range(struct s_range *pRange) {
if (pRange != NULL) {
if (pRange->duplicates != NULL) {
free(pRange->duplicates);
}
free(pRange);
}
}
void drop_allranges(struct s_range *pTopRange) {
struct s_range *lRange;
while (pTopRange != NULL) {
lRange = pTopRange->next;
drop_range(pTopRange);
pTopRange = lRange;
}
}
int push_duplicates(struct s_range *pRange, unsigned int pValue) {
unsigned int *lDuplicates;
if (pRange == NULL) {
return 2;
}
if (pRange->duplicates == NULL) {
lDuplicates = malloc(sizeof(unsigned int));
} else {
lDuplicates = realloc(pRange->duplicates, (pRange->duplicates_count + 1) * sizeof(unsigned int));
}
if (lDuplicates == NULL) {
perror("push_duplicates: failed to allocate...");
return 1;
}
lDuplicates[pRange->duplicates_count++] = pValue;
pRange->duplicates = lDuplicates;
return 0;
}
int pushall_duplicates(struct s_range *pRangeDst, struct s_range *pRangeSrc) {
unsigned int *lDuplicates;
if (pRangeDst == NULL || pRangeSrc == NULL) {
return 2;
}
if (pRangeSrc->duplicates == NULL) {
return 0;
}
if (pRangeDst->duplicates == NULL) {
lDuplicates = malloc(pRangeSrc->duplicates_count * sizeof(unsigned int));
} else {
lDuplicates = realloc(pRangeDst->duplicates, (pRangeDst->duplicates_count + pRangeSrc->duplicates_count) * sizeof(unsigned int));
}
if (lDuplicates == NULL) {
perror("pushall_duplicates: failed to allocate...");
return 1;
}
memcpy(&lDuplicates[pRangeDst->duplicates_count], pRangeSrc->duplicates, pRangeSrc->duplicates_count * sizeof(unsigned int));
pRangeDst->duplicates_count += pRangeSrc->duplicates_count;
pRangeDst->duplicates = lDuplicates;
return 0;
}
int main(int nbargs, char *argv[]) {
struct s_range *lHeapTop = NULL;
struct s_range *lCurrentRange;
struct s_range *lPreviousRange;
unsigned int lMergeFlag;
unsigned int lValue;
unsigned int lN = 3;
unsigned int lDispFlag = 0;
if (nbargs > 1) {
lN = atoi(argv[1]);
}
if (nbargs > 2) {
lDispFlag = atoi(argv[2]);
}
while(fread(&lValue, sizeof(unsigned int), 1, stdin) > 0) {
if (lValue >= lN) {
lCurrentRange = lHeapTop;
lPreviousRange = NULL;
lMergeFlag = 0;
while(lCurrentRange != NULL) {
if (lCurrentRange->min - 1 == lValue) {
lCurrentRange->min = lValue;
lMergeFlag = 1;
break;
}
if (lCurrentRange->max + 1 == lValue) {
lCurrentRange->max = lValue;
lMergeFlag = 1;
break;
}
if (lValue < lCurrentRange->min) {
lCurrentRange = NULL;
break;
}
if (lValue >= lCurrentRange->min && lValue <= lCurrentRange->max) {
if (push_duplicates(lCurrentRange, lValue) != 0) {
drop_allranges(lHeapTop);
return 1;
}
break;
}
lPreviousRange = lCurrentRange;
lCurrentRange = lCurrentRange->next;
}
if (lCurrentRange != NULL) {
if (lMergeFlag == 1) {
if (lPreviousRange != NULL && lCurrentRange->min - 1 == lPreviousRange->max) {
lPreviousRange->max = lCurrentRange->max;
if (pushall_duplicates(lPreviousRange, lCurrentRange) != 0) {
drop_allranges(lHeapTop);
return 1;
}
lPreviousRange->next = lCurrentRange->next;
drop_range(lCurrentRange);
} else {
if (lCurrentRange->next != NULL && lCurrentRange->max + 1 == lCurrentRange->next->min) {
lPreviousRange = lCurrentRange->next;
lCurrentRange->max = lPreviousRange->max;
if (pushall_duplicates(lCurrentRange, lPreviousRange) != 0) {
drop_allranges(lHeapTop);
return 1;
}
lCurrentRange->next = lPreviousRange->next;
drop_range(lPreviousRange);
}
}
}
} else {
if (lPreviousRange == NULL) {
lCurrentRange = new_range(lValue, lValue, lHeapTop);
if (lCurrentRange == NULL) {
drop_allranges(lHeapTop);
return 1;
}
lHeapTop = lCurrentRange;
} else {
lCurrentRange = new_range(lValue, lValue, lPreviousRange->next);
if (lCurrentRange == NULL) {
drop_allranges(lHeapTop);
return 1;
}
lPreviousRange->next = lCurrentRange;
}
}
}
}
// Check the results
if (lDispFlag == 1) {
lCurrentRange = lHeapTop;
while(lCurrentRange != NULL) {
printf("From %u to %u dup:", lCurrentRange->min, lCurrentRange->max);
for (unsigned int lInd = 0; lInd < lCurrentRange->duplicates_count; lInd++) {
printf(" %u", lCurrentRange->duplicates[lInd]);
}
printf("\n");
lCurrentRange = lCurrentRange->next;
}
}
// Cleaning
drop_allranges(lHeapTop);
return 0;
}
With a discrete uniform distribution set of 65 536 words, on a x64 Debian Buster (4670K CPU), this code (range executable) is three times faster than a classic min heap one (node executable):
bash:~$ awk 'BEGIN { for (idx=0;idx<65536;idx++) { v=rand()*256; v2=rand()*256; printf("%c%c%c%c",v,v2,0,0); }}' > data.bin
bash:~$ time cat data.bin | ./range 3
real 0m5.629s
user 0m5.516s
sys 0m0.031s
bash:~$ time cat data.bin | ./node 3
real 0m15.618s
user 0m15.328s
sys 0m0.016s
I'm trying to run a hello world program with the brainfuck implementation that I made this week but I'm getting a strange output.
This is the hello world file that I'm trying to run.
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.-------
-.>>+.>++.
I have saved it to hello.txt, and am parsing it in the main function of the program.
The output is
1 -3 4 4 7 0 -1 7 10 4 -4 1 2
which, when you add 72, and convert to character , gives
I E L L O H G O R L D I J
So it seems like there is something I'm missing, even though its sort of close to the right solution.
But I'll go into the structure of the thing anyhow, the general idea is as followed:
We have two 'tapes', a program to follow which I label 'parsed' which has a pointer 'attached' to it, and an empty tape to write into, which I label 'mem', which also has a pointer 'attached' to it. We also have a list of structures that we can use to jump between bracket locations.
In the main function, there are three parts: first I parse the program and store it in an array. Then I run through this parsing and match brackets, then I start the brainfuck loop and write the output onto the empty array, until the final character has been reached.
In the brainfuck loop, when we find a bracket, we run through the list of pairs to find its match, and then jump to that location.
Maybe it's a bit clunky, but I hope it makes sense.
#include <stdio.h>
#include <stdlib.h>
#define MAX 30000
//input tape
char parsed[MAX];
char * ptr;
//bracket matching
struct bracketlinks{
char * bracket_1;
char * bracket_2;
};
struct bracketlinks * pairslist;
int bracket_count;
//output tape
char mem[MAX] = {0};
int * mptr;
int main(){
mptr = malloc(sizeof(int));
//parse text file and make list of tokens
FILE * parsecode;
parsecode = fopen("helloworldbf.txt", "r");
int count = 0;
char buffer;
while(!feof(parsecode)){
buffer = fgetc(parsecode);
if(buffer == 10){break;}
if(buffer == 32){continue;}
else{
parsed[count] = buffer;
if(buffer == 91 || buffer == 93){
bracket_count++;
}
count++;
}
}
fclose(parsecode);
pairslist = malloc(bracket_count * sizeof(char*));
//creates array of structures which match brackets so we can perform memory jumps
int reset_count;
int list_counter = 0;
for(int i = 0; i < count; i++){
if(parsed[i] == '['){
reset_count = 0;
for(int j = 0; j < count - i + 1; j++){
if(parsed[i + j] == '['){reset_count++;}
if(parsed[i + j] == ']'){reset_count--;}
if(reset_count == 0){
struct bracketlinks new;
new.bracket_1 = &parsed[i];
new.bracket_2 = &parsed[i + j];
pairslist[list_counter] = new;
list_counter++;
break;
}
else{continue;}
}
}
else{continue;}
}
//runs through the input tape and performs operations on the output tape
ptr = parsed;
char final_token = ptr[count];
while(ptr[0] != final_token){
if(ptr[0] == '['){
if(mem[mptr[0]]){++ptr;}
if(!mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
}
if(ptr[0] == ']'){
if(!mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
if(mem[mptr[0]]){++ptr;}
else{continue;}
}
if(ptr[0] == '+'){++ptr;++mem[mptr[0]];}
if(ptr[0] == '-'){++ptr;--mem[mptr[0]];}
if(ptr[0] == '>'){++ptr; mptr[0]++;}
if(ptr[0] == '<'){mptr[0]--;++ptr;}
if(ptr[0] == '.'){++ptr; printf("%c %d \n", mem[mptr[0]] + 72, mem[mptr[0]]);}
else{continue;}
}
free(pairslist);
free(mptr);
return 0;
}
Any help would be massively appreciated,
Cheers..
OK so here's the fix for the main bug: basically just switch the exclamation marks and don't be a numpty.
if(ptr[0] == ']'){
if(mem[mptr[0]]){
for(int i = 0; i < bracket_count/2; i++){
if(pairslist[i].bracket_1 == &ptr[0]){
ptr = ++pairslist[i].bracket_2;
}
if(pairslist[i].bracket_2 == &ptr[0]){
ptr = ++pairslist[i].bracket_1;
}
else{continue;}
}
}
if(!mem[mptr[0]]){++ptr;}
else{continue;}
}
Still working on the !feof thing but will update with that too
We have a project that controls a led strip of 80, that is connected via mobile app. The components we used are as follows:
Arduino Nano Board
HM - 10 Bluetooth module
WS2812b Led Strip
On the app, user selects the colors(up to 5), animation (optional), animation speed and brightness. The selected configuration is transmitted to the BLE module with a certain throttle and debouncing. The color(selected on a color wheel on the app) and brightness transmits fine, without any issues.
The problem we encounter, is that when certain animation is active, if the user changes the animation speed via the app, the arduino part locks itself and will not accept any more commands.
To activate a configuration with animation, we send the data from app to arduino as follows:
<l255180200,240135068:089;04200>
The format is: < [mode] [colors(with ',')] : [brightness] ; [animationCode(2 digit)] [animationSpeed] >
At first, we had some inconsistencies with consecutive data, so we implemented the following for data acquisition:
void loop()
{
// Read all serial data available, as fast as possible
while (bleSerial.available() > 0)
{
char inChar = bleSerial.read();
if (inChar == SOP)
{
index = 0;
inData[index] = '\0';
started = true;
ended = false;
}
else if (inChar == EOP)
{
ended = true;
break;
}
else
{
if (index < 79)
{
inData[index] = inChar;
index++;
inData[index] = '\0';
}
}
}
// We are here either because all pending serial
// data has been read OR because an end of
// packet marker arrived. Which is it?
if (started && ended)
{
// The end of packet marker arrived. Process the packet
Serial.println(inData);
Serial.println(inData[0]);
char mode = inData[0];
if (mode == 'p')
{
togglePower(inData);
finalizeRead();
return;
}
if (mode == 'b')
{
changeBrightness(inData);
finalizeRead();
return;
}
if (mode == 't')
{
char *themeNo = strtok(NULL, ";");
int themeCode = valueFromString(themeNo, 0, 2);
theme(themeCode);
}
// if (mode == 'e') {
// sound();
// return;
// }
char *colorsWithBrightness = strtok(inData, ";");
char *animation = strtok(NULL, ";");
char *colors = strtok(colorsWithBrightness, ":");
char *brightness = strtok(NULL, ":");
custom(colors, brightness, animation);
finalizeRead();
}
}
void finalizeRead()
{
// Reset for the next packet
started = false;
ended = false;
index = 0;
inData[index] = '\0';
}
int valueFromString(char *string, int start, int width)
{
int value = 0;
for (int n = 0; n < width; n++)
value = value * 10 + string[start + n] - '0';
return value;
}
So the custom function is called when the mode == 'l'. And in custom function, we perform as follows:
void custom(char *colors, char *brightness, char *animation)
{
char *trueColors = strtok(colors, "l");
char *colorsSplit = strtok(trueColors, ",");
int colorCount = 0;
uint32_t colorArray[5] = {};
while (colorsSplit != NULL)
{
int r = valueFromString(colorsSplit, 0, 3);
int g = valueFromString(colorsSplit, 3, 3);
int b = valueFromString(colorsSplit, 6, 3);
colorArray[colorCount] = strip.Color(r, g, b);
colorCount++;
colorsSplit = strtok(NULL, ",");
}
int ledsPerSegment = ledCount / colorCount;
for (int n = 0; n < colorCount; n++)
{
int currentSegment = (n + 1) * ledsPerSegment;
Serial.println(currentSegment);
for (int z = n * ledsPerSegment; z < (n + 1) * ledsPerSegment; z++)
{
strip.setPixelColor(z, colorArray[n]);
}
}
strip.setBrightness(atoi(brightness));
strip.show();
Serial.println("Done");
if (animation)
{
int animationCode = valueFromString(animation, 0, 2);
int animationSpeed = valueFromString(animation, 2, 3);
Serial.println(animationSpeed);
if (animationCode == 1)
breath(animationSpeed, atoi(brightness));
else if (animationCode == 7)
pulse(animationSpeed, colorArray, colorCount);
}
}
The problem occurs in pulse animation, which is like this:
void pulse(int wait, uint32_t colorArray[], int colorCount)
{
black();
while (bleSerial.available() <= 0)
{
for (i = 0; i < colorCount && bleSerial.available() <= 0; i++)
{
for (j = 0; j < ledCount / 2 && bleSerial.available() <= 0; j++)
{
strip.setPixelColor(39 - j, colorArray[i]);
strip.setPixelColor(40 + j, colorArray[i]);
strip.show();
delay(wait);
}
black();
}
}
}
We initialize the animation without any issues using the following:
<l255180200,240135068:089;04200>
As soon as we adjust the animation speed from the app, we send about 2 new configurations per second, which is the same as above, only with different speed (last 3 characters before '>'). The arduino part randomly receives the data incorrectly, losing 2-3 characters, which is like <l2551800,240135068:089;04200>
The loss of characters usually occurs on different parts of the string, but always consecutive characters are misread happen each time. Also, sometimes we get a backwards question mark.
We are not sure where we implement wrong, so any help is appreciated on solving this issue.
Thanks!
I have to get the number of sign changes in a list of doubles. For example if there is a list like that: "1, -1, -1, 1" there are 2 sign changes, between the adjacent elements. I tried it like this but for some reason the program crashes if I try to compile it:
int number_of_sign_changes(DoubleList* list) {
int changes = 0;
for (DoubleNode *n = list->first; n != NULL; n = n->next) {
if ((n->value >= 0) && (n->next->value < 0)) {
changes += 1;
} else if ((n->value < 0) && (n->next->value >= 0)) {
changes += 1;
}
}
return changes;
}
The loop definitely works. I tried it in other functions but here it won't work. Does anyone have an idea? Btw you could actually put the 2 if statements into 1 and I tried that aswell but same problem.
This is in essence a fence post problem. The number of possible sign changes is one less than the number of elements in the list, so as you are checking on each item, you can tell you are doing something wrong. The problem in fact occurs when checking the last item on the list - it attempts to check for a sign change to the 'next' item, and there isn't one, as n->next is NULL.
This can be fixed by a simple change to the terminating condition in the for loop as follows:
int number_of_sign_changes(DoubleList* list) {
int changes = 0;
for (DoubleNode *n = list->first; n != NULL && n->next != NULL; n = n->next) {
if ((n->value >= 0) && (n->next->value < 0)) {
changes += 1;
} else if ((n->value < 0) && (n->next->value >= 0)) {
changes += 1;
}
}
return changes;
}