Arduino Compare Weights of an Array - arrays

I am trying to get a sensor to scan around and mark an object by assigning a 1 to that position. The positions are from 30 60 90 120 150 [ 0 0 0 0 0]. I then wanted to take that aray and compare it to memory ( tempArray vs memArray) and decide which way to turn. Essentially obstacle avoidance, any suggestions on how to implement this with arrays?
void scan() {
servo.write(30);
delay(350);
rScan = echodis();
if (rScan > distanceLimit) {
tempArray[4] = 1;
}
servo.write(60);
delay(350);
rDiagScan = echodis();
if (rDiagScan > distanceLimit) {
tempArray[3] = 1;
}
servo.write(90);
delay(350);
cScan = echodis();
if (cScan > distanceLimit) {
tempArray[2] = 1;
}
servo.write(120);
delay(350);
lDiagScan = echodis();
if (lDiagScan > distanceLimit) {
tempArray[1] = 1;
}
servo.write(150);
delay(350);
lScan = echodis();
if (lScan > distanceLimit) {
tempArray[0] = 1;
}
scanCount++;
servo.write(120);
delay(350);
lDiagScan = echodis();
if (lDiagScan > distanceLimit) {
tempArray[1] = 1;
} servo.write(90);
delay(350);
cScan = echodis();
if (cScan > distanceLimit) {
tempArray[2] = 1;
}
servo.write(60);
delay(350);
rDiagScan = echodis();
if (rDiagScan > distanceLimit) {
tempArray[3] = 1;
}
servo.write(30);
delay(350);
rScan = echodis();
if (rScan > distanceLimit) {
tempArray[4] = 1;
}
scanCount++;
//if(scanCount = 4){
//memset(tempArray, 0, sizeof(tempArray));
//}
//return (tempArray);
}

There are many ways to solve such problems in repetition, here's one.
The approach here is to let state and data drive the operations rather than massively repetitive, bug prone code. Also consider the importance of defining minimums, maximums, constants etc in one place.
#define SERVO_SETTLE_MILLIS 350
#define SERVO_STEP 30
#define SERVO_SAMPLE_LEN 5
#define OUTLIER 1
#define INLIER 0
byte scan_count = 0; // when even or 0, position starts at 30. when odd, position starts at 150.
void scan(byte* pSampleArray, const uint16_t maxDistance) {
byte direction = scan_count % 2 == 0;
byte servo_position = direction ? (SERVO_SAMPLE_LEN * SERVO_STEP) : 0;
byte sample_index = direction ? SERVO_SAMPLE_LEN : -1;
for (byte i = 0; i < SERVO_SAMPLE_LEN; i++) {
// direction == 0 == servo position starts at 30 (initial)
if (direction) {
sample_index--; // e.g. 4,3,2,1,0
servo_position += SERVO_STEP; // e.g. 30,60,90,120,150
}
else
{
sample_index++; // e.g. 0,1,2,3,4
servo_position -= SERVO_STEP;; // e.g. 150,120,90,60,30
}
// position servo
servo.write(servo_position);
// settling time
delay(SERVO_SETTLE_MILLIS);
// sample = 1 if outlier, 0 otherwise
pSampleArray[sample_index] = echodis() > maxDistance ? OUTLIER : INLIER;
}
scan_count++; // implies direction stepping for next call to scan.
}
Of course care must be taken that pSampleArray can accomodate 5 samples.
You don't speak of what you plan to do with "arrays" which is probably the real meat of your project, but for example consider function foo
void foo(const uint16_t maxDistance) {
byte sample1[SERVO_SAMPLE_LEN];
byte sample2[SERVO_SAMPLE_LEN];
scan(sample1, maxDistance);
delay(1000);
scan(sample2, maxDistance);
//
// process your samples
//
}
Good luck!

Related

Binary search loop is not breaking when the search element input is not prsenting in the sorted array

I am implementing the binary search in C as below, but when I'm passing the element which is not available in the sorted array, the code is enter into infinite loop since the midelement is repetitively calculating the same value (midelement is 4, and then start index becomes 5 (elementtofind > InputArray[midelement]), end index is 4, hence again returns the mid element as 4) after the 9th iteration of the loop, can anyone find how could I improve this logic.
#define MAX_NUM_INPUT (358U)
uint16 InputArray[MAX_NUM_INPUT] = {0x0103, 0x0104, 0x0109, 0x010A, 0x0133, 0x0180, 0x181, 0x183,.....upto 358 elements};
int main()
{
boolean elmntFound = 0;
uint16 elmntTofnd = 0x0134;
elmntFound = SearchPassedElement(0, MAX_NUM_INPUT, elmntTofnd);
if(elmntFound == 0)
{
printf("elementfound");
}
else
{
printf("elementNOTfound");
}
}
static boolean SearchPassedElement (uint16 FrstElmntIdx,uint16 LstElmntIdx, uint16 ElmntToFind)
{
boolean ReturnValue = 1;
uint16 startIdx = FrstElmntIdx;
uint16 endIdx = LstElmntIdx;
uint16 loc_midElmntIdx;
boolean OperationStatus = FALSE;
if(LstElmntIdx >= FrstElmntIdx)
{
while (OperationStatus == FALSE)
{
loc_midElmntIdx = (startIdx + endIdx) / 2U ;
if (ElmntToFind == InputArray[loc_midElmntIdx])
{
OperationStatus = TRUE;
ReturnValue = 0 ;
}
else if (ElmntToFind > InputArray[loc_midElmntIdx])
{
/* if entire array was already checked*/
if (startIdx == endIdx)
{
OperationStatus = TRUE;
ReturnValue = 1 ;
}
else /* othewise, */
{
startIdx = loc_midElmntIdx + 1U;
}
}
else
{
/* if entire array was already checked*/
if (startIdx == endIdx)
{
OperationStatus = TRUE;
ReturnValue = 1 ;
}
else /* othewise, */
{
endIdx = loc_midElmIdx - 1U ;
}
}
}
}
else
{
loopCntr = 0;
/* Incorrect input arguments */
ReturnValue = 1;
}
return ReturnValue;
}
I have found one logic as if the midelemnt is returned with same value for more than 3 times the lop shall be breaked, and evaluating the same.
static boolean SearchPassedElement (uint16 FrstElmntIdx,uint16 LstElmntIdx, uint16 ElmntToFind)
{
boolean ReturnValue = 1;
uint16 startIdx = FrstElmntIdx;
uint16 endIdx = LstElmntIdx;
uint16 loc_midElmntIdx;
boolean OperationStatus = FALSE;
uint16 prev_loc_midElmIdx = 0;
uint16 is_midElmIdxSame_count = 0;
if(LstElmntIdx >= FrstElmntIdx)
{
while (OperationStatus == FALSE)
{
loc_midElmntIdx = (startIdx + endIdx) / 2U ;
if (ElmntToFind == InputArray[loc_midElmntIdx])
{
OperationStatus = TRUE;
ReturnValue = 0 ;
}
else if (ElmntToFind > InputArray[loc_midElmntIdx])
{
/* if entire array was already checked*/
if (startIdx == endIdx)
{
OperationStatus = TRUE;
ReturnValue = 1 ;
}
else /* othewise, */
{
startIdx = loc_midElmntIdx + 1U;
}
}
else
{
/* if entire array was already checked*/
if (startIdx == endIdx)
{
OperationStatus = TRUE;
ReturnValue = 1 ;
}
else /* othewise, */
{
endIdx = loc_midElmIdx - 1U ;
}
}
if(prev_loc_midElmIdx != loc_midElmIdx)
{
prev_loc_midElmIdx = loc_midElmIdx;
}
else
{
is_midElmIdxSame_count++;
/*as the divisor is 2 the same value can't return more that 2 times, hence if the same value is return more than
* 2 times the loop should be braked
*/
if(is_midElmIdxSame_count == 3)
{
elmntNotFnd = 3;
/* Stop operation and return failure*/
OperationStatus = TRUE;
ReturnValue = 1 ;
}
}
}
}
else
{
loopCntr = 0;
/* Incorrect input arguments */
ReturnValue = 1;
}
return ReturnValue;
}
There's no such type called boolean in C. You have to #include <stdbool.h> to use the bool type. The same thing for uint16, you have to #include <stdint.h> and use uint16_t.
And your code is very complicated. You needlessly use a lot of variables to get one simple thing done.
Here is a more compact version:
bool binary_search(size_t start, size_t end, const uint16_t elem, const uint16_t array[])
{
while (start < end) {
size_t middle = (start + end) / 2;
if (elem == array[middle])
return true;
if (elem < array[middle])
end = middle;
else
start = middle + 1;
}
return false;
}
It returns true if the element is found, false otherwise.
Example:
int main(void)
{
uint16_t array[] = {1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U};
const size_t size = sizeof array / sizeof array[0];
const uint16_t elem = 10U;
printf("%s\n", binary_search(0, size, elem, array) ? "Found" : "Not found");
}
Found
Few things to note:
size_t is the appropriate type for indexing arrays.
Use const (i.e. read-only) when you don't modify your variables.
Don't write C in Pascal style.

Find three or more consecutive characters in the same struct in C

I define a struct.
struct test
{
char name[10];
int num;
}temp[20];
I want to only output the data with the same name and three consecutive num or more in temp[20].
for example,the data of the temp[20] are as follows:
temp[0] = { "a",0 };
temp[1] = { "b",1 };
temp[2] = { "a",2 };
temp[3] = { "b",2 };
temp[4] = { "a",3 };
temp[5] = { "b",3 };
temp[6] = { "a",4 };
temp[7] = { "c",1 };
temp[8] = { "c",2 };
temp[9] = { "a",5 };
........
the output is
temp[2] = { "a",2 };
temp[4] = { "a",3 };
temp[6] = { "a",4 };
temp[9] = { "a",5 };
temp[1] = { "b",1 };
temp[3] = { "b",2 };
temp[5] = { "b",3 };
I can only use a triple for loop to output data with the same name and three consecutive num,but four consecutive num can`t output.My code are as follows:
for (int i = 0; i < 20; i++)
{
for (int j = i + 1;j < 20;j++) {
if ((strcmp(temp[i].name, temp[j].name) == 0) && (temp[j].num - temp[i].num == 1))
{
for (int k = 0; k < 20; k++)
{
if ((strcmp(temp[k].name, temp[j].name) == 0) && (temp[k].num - temp[j].num == 1)) {
printf("%s,%d", temp[i].name, temp[i].num);
printf("%s,%d", temp[j].name, temp[j].num);
printf("%s,%d", temp[k].name, temp[k].num);
}
}
}
}
}
what could I do?
Since you haven't specified anything particular about the data's ordering, I assume that it's fine to sort it. Sorting by the name, then number allows you to find consecutive runs of values in linear time. And a typically sorting algorithm can be achieved in N.log(N) time.
Let's assume that N represents the number of elements in your array. You can sort it simply like this:
std::sort(temp, temp + N,
[](const test& a, const test& b) {
int result = strcmp(a.name, b.name);
return result < 0 || result == 0 && a.num < b.num;
});
Using a couple of simple helpers to display the data...
void Show(const test& t)
{
std::cout << t.name << "," << t.num << "\n";
}
void Show(const test* t, int N)
{
for (int i = 0; i < N; ++i)
Show(t[i]);
}
Now, after sorting, a call to Show(temp, N); gives this:
a,0
a,2
a,3
a,4
a,5
b,1
b,2
b,3
c,1
c,2
Now it's quite trivial to walk through the array and find runs of some minimum number. You requested 3, but we can choose any number.
const int minRunLength = 3;
std::cout << "Consecutive runs with matching name (minimum " << minRunLength << "):\n";
for (int i = 0, runLength = 0; i < N; ++i)
{
// Update run length
if (i > 0 &&
strcmp(temp[i-1].name, temp[i].name) == 0 &&
temp[i-1].num + 1 == temp[i].num)
{
++runLength;
}
else
{
runLength = 1;
}
// Show items meeting run length criteria
if (runLength == minRunLength)
{
for (int p = runLength-1; p >= 0; --p)
Show(temp[i - p]);
}
else if (runLength > minRunLength)
{
Show(temp[i]);
}
}
Running this with a minimum length of 3 gives:
Consecutive runs with matching name (minimum 3):
a,2
a,3
a,4
a,5
b,1
b,2
b,3
A minimum of 4 is:
Consecutive runs with matching name (minimum 4):
a,2
a,3
a,4
a,5
Here is a Live Demo that you can play with.

QMK RGB saturation bottoms out

RGB keycodes RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, and RGB_VAD allow me to increment or decrement hue, saturation, and value on my RGB underglow lights. But I wanted to be able to hold down a key to change the color continually. So I made these changes:
In config.h:
#ifdef RGBLIGHT_ENABLE
#define RGBLIGHT_HUE_STEP 1
#define RGBLIGHT_SAT_STEP 1
#define RGBLIGHT_VAL_STEP 1
#endif
And then in keymap.c I made the custom keycodes:
enum custom_keycodes {
KC_HUI = SAFE_RANGE,
KC_HUD,
KC_SAI,
KC_SAD,
KC_VAI,
KC_VAD
};
And defined some variables:
// flags. 0 = no change, 1 = increment, -1 = decrement.
int8_t change_hue = 0;
int8_t change_saturation = 0;
int8_t change_value = 0;
// timers to control color change speed
uint16_t hue_timer = 0;
uint16_t saturation_timer = 0;
uint16_t value_timer = 0;
// seconds it takes to cycle through 0-255 or back
// technically 1 = 1.024 seconds, yielding even multiples of 4ms per tick (1024 / 256).
const int8_t hue_seconds = 5;
const int8_t saturation_seconds = 5;
const int8_t value_seconds = 5;
Then I use the keycodes to set the flags and timers:
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_HUI:
if (record->event.pressed) {
hue_timer = timer_read();
change_hue = 1;
} else {
change_hue = 0;
}
break;
case KC_HUD:
if (record->event.pressed) {
hue_timer = timer_read();
change_hue = -1;
} else {
change_hue = 0;
}
break;
case KC_SAI:
if (record->event.pressed) {
saturation_timer = timer_read();
change_saturation = 1;
} else {
change_saturation = 0;
}
break;
case KC_SAD:
if (record->event.pressed) {
saturation_timer = timer_read();
change_saturation = -1;
} else {
change_saturation = 0;
}
break;
case KC_VAI:
if (record->event.pressed) {
value_timer = timer_read();
change_value = 1;
} else {
change_value = 0;
}
break;
case KC_VAD:
if (record->event.pressed) {
value_timer = timer_read();
change_value = -1;
} else {
change_value = 0;
}
break;
}
return true;
}
Then I use a matrix scan to change the color using those flags and timers:
void matrix_scan_user(void) {
switch (change_hue) {
case 0:
break;
case 1:
if (timer_elapsed(hue_timer) > (hue_seconds * 4)) {
hue_timer = timer_read();
rgblight_increase_hue();
}
break;
case -1:
if (timer_elapsed(hue_timer) > (hue_seconds * 4)) {
hue_timer = timer_read();
rgblight_decrease_hue();
}
break;
}
switch (change_saturation) {
case 0:
break;
case 1:
if (timer_elapsed(saturation_timer) > (saturation_seconds * 4)) {
saturation_timer = timer_read();
rgblight_increase_sat();
}
break;
case -1:
if (timer_elapsed(saturation_timer) > (saturation_seconds * 4)) {
saturation_timer = timer_read();
rgblight_decrease_sat();
}
break;
}
switch (change_value) {
case 0:
break;
case 1:
if (timer_elapsed(value_timer) > (value_seconds * 4)) {
value_timer = timer_read();
rgblight_increase_val();
}
break;
case -1:
if (timer_elapsed(value_timer) > (value_seconds * 4)) {
value_timer = timer_read();
rgblight_decrease_val();
}
break;
}
}
According to the docs, each of those should wrap around at the max/min hue/saturation/value, respectively.
That seems to work exactly as expected with KC_HUI and KC_HUD: If I hold the key down long enough it rounds the bend and hue just keeps on cycling through.
KC_SAI, KC_VAI, and KC_VAD work at least normal-ish. I can increase saturation or value to the max and it will just stop there, and likewise if I decrement the value it stops at zero.
KC_SAD is the problem. When I hold it down long enough (just past white), the keyboard bombs out. It turns a weird orange color and nothing works.
For reference, here is the GitHub commit where I made all the changes, along with the rest of my code of course.
Any idea why KC_SAD would bomb out rather than either stopping or wrapping around?
Any idea why both saturation and value just stop, rather than wrapping around as I'd expect based on my read of the docs?
Might I do better to try this whole thing a different way (question to more seasoned users)?
I experimented with this some more, and came up with a different implementation which is much more efficient in terms of lines of code and bytes added to the firmware size. Note that instead of defining new custom keycodes, instead it hijacks the existing RGB_... ones for this new and improved purpose:
#include <lib/lib8tion/lib8tion.h>
// flags. 0 = no change, 1 = increment, -1 = decrement.
int8_t change_hue = 0;
int8_t change_sat = 0;
int8_t change_val = 0;
// timer to control color change speed
uint16_t change_timer = 0;
const uint16_t change_tick = 15;
void matrix_scan_user(void) {
if (change_hue != 0 || change_val != 0 || change_sat != 0) {
if (timer_elapsed(change_timer) > change_tick) {
HSV hsv = rgblight_get_hsv();
hsv.h += change_hue;
hsv.s = change_sat > 0 ? qadd8(hsv.s, (uint8_t) change_sat) : qsub8(hsv.s, (uint8_t) -change_sat);
hsv.v = change_val > 0 ? qadd8(hsv.v, (uint8_t) change_val) : qsub8(hsv.v, (uint8_t) -change_val);
rgblight_sethsv_noeeprom(hsv.h, hsv.s, hsv.v);
change_timer = timer_read();
}
}
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
switch (keycode) {
// clang-format off
case RGB_HUI: change_timer = timer_read(); change_hue = 1; return false;
case RGB_HUD: change_timer = timer_read(); change_hue = -1; return false;
case RGB_SAI: change_timer = timer_read(); change_sat = 1; return false;
case RGB_SAD: change_timer = timer_read(); change_sat = -1; return false;
case RGB_VAI: change_timer = timer_read(); change_val = 1; return false;
case RGB_VAD: change_timer = timer_read(); change_val = -1; return false;
// clang-format on
}
} else {
bool rgb_done = false;
switch (keycode) {
case RGB_HUI:
case RGB_HUD:
change_hue = 0;
rgb_done = true;
break;
case RGB_SAI:
case RGB_SAD:
change_sat = 0;
rgb_done = true;
break;
case RGB_VAI:
case RGB_VAD:
change_val = 0;
rgb_done = true;
break;
}
if (rgb_done) {
HSV final = rgblight_get_hsv();
rgblight_sethsv(final.h, final.s, final.v);
}
}
return true;
}
This is a really nice bit of functionality!
I copied your code into one of my keyboards, and I am not able to reproduce the "bomb out" behavior that you are seeing on KC_SAD.
The documentation is incorrect. The increase/decrease functions for saturation and value do not wrap around, and to my knowledge, they are not intended to wrap. They max out at 255, and are bottom limited at 0. I'll be filing a PR to fix the documentation.
The only significant problem that I see with your implementation is that it results in VERY many writes to eeprom, and that isn't healthy (they wear out over time). You should use, for instance, rgblight_increase_sat_noeeprom() to adjust the saturation (and its counterparts for hue / saturation, and for decrease). Then when you release the key, only then should you write the current HSV setting to eeprom (using rgblight_sethsv() to set the final value into eeprom.

Cell Compete Problems

Here is my assignment:
There is a colony of 8 cells arranged in a straight line where each day every cell competes with its adjacent cells(neighbour). Each day, for each cell, if its neighbours are both active or both inactive, the cell becomes inactive the next day,. otherwise itbecomes active the next day.
Assumptions: The two cells on the ends have single adjacent cell, so
the other adjacent cell can be assumsed to be always inactive. Even
after updating the cell state. consider its pervious state for
updating the state of other cells. Update the cell informationof
allcells simultaneously.
Write a fuction cellCompete which takes takes one 8 element array of
integers cells representing the current state of 8 cells and one
integer days representing te number of days to simulate. An integer
value of 1 represents an active cell and value of 0 represents an
inactive cell.
Program:
int* cellCompete(int* cells,int days)
{
//write your code here
}
//function signature ends
Test Case 1:
INPUT:
[1,0,0,0,0,1,0,0],1
EXPECTED RETURN VALUE:
[0,1,0,0,1,0,1,0]
Test Case 2:
INPUT:
[1,1,1,0,1,1,1,1,],2
EXPECTED RETURN VALUE:
[0,0,0,0,0,1,1,0]
This is the problem statement given above for the problem. The code which I have written for this problem is given below. But the output is coming same as the input.
#include<iostream>
using namespace std;
// signature function to solve the problem
int *cells(int *cells,int days)
{ int previous=0;
for(int i=0;i<days;i++)
{
if(i==0)
{
if(cells[i+1]==0)
{
previous=cells[i];
cells[i]=0;
}
else
{
cells[i]=0;
}
if(i==days-1)
{
if(cells[days-2]==0)
{
previous=cells[days-1];
cells[days-1]=0;
}
else
{
cells[days-1]=1;
}
}
if(previous==cells[i+1])
{
previous=cells[i];
cells[i]=0;
}
else
{
previous=cells[i];
cells[i]=1;
}
}
}
return cells;
}
int main()
{
int array[]={1,0,0,0,0,1,0,0};
int *result=cells(array,8);
for(int i=0;i<8;i++)
cout<<result[i];
}
I am not able to get the error and I think my logic is wrong. Can we apply dynamic programming here If we can then how?
private List<Integer> finalStates = new ArrayList<>();
public static void main(String[] args) {
// int arr[] = { 1, 0, 0, 0, 0, 1, 0, 0 };
// int days = 1;
EightHousePuzzle eightHousePuzzle = new EightHousePuzzle();
int arr[] = { 1, 1, 1, 0, 1, 1, 1, 1 };
int days = 2;
eightHousePuzzle.cellCompete(arr, days);
}
public List<Integer> cellCompete(int[] states, int days) {
List<Integer> currentCellStates = Arrays.stream(states).boxed().collect(Collectors.toList());
return getCellStateAfterNDays(currentCellStates, days);
}
private List<Integer> getCellStateAfterNDays(List<Integer> currentCellStates, int days) {
List<Integer> changedCellStates = new ArrayList<>();
int stateUnoccupied = 0;
if (days != 0) {
for (int i1 = 0; i1 < currentCellStates.size(); i1++) {
if (i1 == 0) {
changedCellStates.add(calculateCellState(stateUnoccupied, currentCellStates.get(i1 + 1)));
} else if (i1 == 7) {
changedCellStates.add(calculateCellState(currentCellStates.get(i1 - 1), stateUnoccupied));
} else {
changedCellStates
.add(calculateCellState(currentCellStates.get(i1 - 1), currentCellStates.get(i1 + 1)));
}
}
if (days == 1) {
System.out.println("days ==1 hit");
finalStates = new ArrayList<>(changedCellStates);
return finalStates;
}
days = days - 1;
System.out.println("Starting recurssion");
getCellStateAfterNDays(changedCellStates, days);
}
return finalStates;
}
private int calculateCellState(int previousLeft, int previousRight) {
if ((previousLeft == 0 && previousRight == 0) || (previousLeft == 1 && previousRight == 1)) {
// the state gets now changed to 0
return 0;
}
// the state gets now changed to 0
return 1;
}
Here is my solution in Java:
public class Colony
{
public static int[] cellCompete(int[] cells, int days)
{
int oldCell[]=new int[cells.length];
for (Integer i = 0; i < cells.length ; i++ ){
oldCell[i] = cells[i];
}
for (Integer k = 0; k < days ; k++ ){
for (Integer j = 1; j < oldCell.length - 1 ; j++ ){
if ((oldCell[j-1] == 1 && oldCell[j+1] == 1) || (oldCell[j-1] == 0 && oldCell[j+1] == 0)){
cells[j] = 0;
} else{
cells[j] = 1;
}
}
if (oldCell[1] == 0){
cells[0] = 0;
} else{
cells[0] = 1;
}
if (oldCell[6] == 0){
cells[7] = 0;
} else{
cells[7] = 1;
}
for (Integer i = 0; i < cells.length ; i++ ){
oldCell[i] = cells[i];
}
}
return cells;
}
}
Your program does not distinguish between the number of days to simulate and the number of cells.
#include <bits/stdc++.h>
using namespace std;
int* cellCompete(int* cells,int days)
{
for(int j=0; j<days; j++)
{
int copy_cells[10];
for(int i=1; i<9; i++)
copy_cells[i]=cells[i-1];
copy_cells[0]=0;copy_cells[9]=0;
for(int i=0; i<8; i++)
cells[i]=copy_cells[i]==copy_cells[i+2]?0:1;
}
return cells;
}
int main()
{
int arr[8]={1,1,1,0,1,1,1,1};
int arr2[8]={1,0,0,0,0,1,0,0};
cellCompete(arr2,1);
for(int i=0; i<8; i++)
{
cout<<arr2[i]<<" ";
}
}
Here's some sweet little python code:
def cell(arr, days):
new = arr[:] #get a copy of the array
n = len(arr)
if n == 1: print [0] #when only 1 node, return [0]
for _ in range(days):
new[0] = arr[1] #determine the edge nodes first
new[n - 1] = arr[n - 2]
for i in range(1, n-1):
new[i] = 1 - (arr[i-1] == arr[i+1]) #logic for the rest nodes
arr = new[:] #update the list for the next day
return new
arr = [1, 1, 1, 0, 1, 1, 1, 1]
days = 2
print cell(arr, days)
You can easily do this in Javascript with few lines of code
let cells = [1,1,1,0,1,1,1,1];
let numOfDays = 2;
let changeState = (cellarr)=> cellarr.map((cur, idx, arr)=> (arr[idx-1] ||0) + (arr[idx+1] || 0)===1?1:0);
let newCells =cells;
for (let i = 0 ; i <numOfDays; i++) newCells = changeState(newCells);
console.log(newCells);
This is a C# version of a possible answer. I really struggled with this for a while for some reason!
I also incorporated some of Janardan's stuff above as it helped spur me in the right direction. (cheers!)
The tricky part of the question was dealing with the fact that you had to persist the state of the cell to figure out the next cell competition which I had originally tried with a second array which was messy.
Note: I chose to use the Array.Copy method as I believe it is slightly more efficient and a lot more readable than copying arrays with a for loop when reading through.
Hopefully this helps someone out in the future!
public int[] cellCompete(int[] cell, int day)
{
//First create an array with an extra 2 cells (these represent the empty cells on either end)
int[] inputArray = new int[cell.Length + 2];
//Copy the cell array into the new input array leaving the value of the first and last indexes as zero (empty cells)
Array.Copy(cell, 0, inputArray, 1, cell.Length);
//This is cool I stole this from the guy above! (cheers mate), this decrements the day count while checking that we are still above zero.
while (day-- > 0)
{
int oldCellValue = 0;
//In this section we loop through the array starting at the first real cell and going to the last real cell
//(we are not including the empty cells at the ends which are always inactive/0)
for (int i = 1; i < inputArray.Length - 1; i++)
{
//if the cells below and above our current index are the same == then the target cell will be inactive/0
//otherwise if they are different then the target cell will be set to active/1
//NOTE: before we change the index value to active/inactive state we are saving the cells oldvalue to a variable so that
//we can use that to do the next "cell competition" comparison (this fulfills the requirement to update the values at the same time)
if (oldCellValue == inputArray[i + 1])
{
oldCellValue = inputArray[i];
inputArray[i] = 0;
}
else
{
oldCellValue = inputArray[i];
inputArray[i] = 1;
}
}
}
//Finally we create a new output array that doesn't include the empty cells on each end
//copy the input array to the output array and Bob's yer uncle ;)...(comments are lies)
int[] outputArray = new int[cell.Length];
Array.Copy(inputArray, 1, outputArray, 0, outputArray.Length);
return outputArray;
}
With C#
public static int[] cellCompete(int[] states, int days)
{
if (days == 0) return states;
int leftValue = 0;
int rigthValue = 0;
for (int i = 0; i < states.Length; i++)
{
if (i == states.Length - 1)
rigthValue = 0;
else
rigthValue = states[i + 1];
if (leftValue == rigthValue){
leftValue = states[i];
states[i] = 0;
}
else{
leftValue = states[i];
states[i] = 1;
}
}
cellCompete(states, days - 1);
return states;
}
I think some of the answers above could be more readable (in addition to being more efficient). Use an additional array and alternate updates between them depending on the number of days. You can return the most recently updated array, which will always be the correct one. Like this:
function cellCompete(states, days) {
const newStates = [];
let originalStates = true;
while (days--) {
changeStates(
originalStates ? states : newStates,
originalStates ? newStates : states,
states.length
);
originalStates = !originalStates;
}
return originalStates ? states : newStates;
}
function changeStates(states, newStates, len) {
newStates[0] = !states[1] ? 0 : 1;
newStates[len-1] = !states[len-2] ? 0 : 1;
for (let i = 1; i < len - 1; i++) {
newStates[i] = states[i-1] === states[i+1] ? 0 : 1;
}
}
Here is my solution in c++ using bitwise operators :
#include <iostream>
using namespace std;
void cellCompete( int *arr, int days )
{
int num = 0;
for( int i = 0; i < 8; i++ )
{
num = ( num << 1 ) | arr[i];
}
for( int i = 0; i < days; i++ )
{
num = num << 1;
num = ( ( ( num << 1 ) ^ ( num >> 1 ) ) >> 1 ) & 0xFF;
}
for( int i = 0; i < 8; i++ )
{
arr[i] = ( num >> 7 - i ) & 0x01;
}
}
int main()
{
int arr[8] = { 1, 0, 0, 0, 0, 1, 0, 0};
cellCompete( arr, 1 );
for(int i = 0; i < 8; i++)
{
cout << arr[i] << " ";
}
}
#include <stdio.h>
int main() {
int days,ind,arr[8],outer;
for(ind=0;ind<8;scanf("%d ",&arr[ind]),ind++); //Reading the array
scanf("%d",&days);
int dupArr[8];
for(outer=0;outer<days;outer++){ //Number of days to simulate
for(ind=0;ind<8;ind++){ //Traverse the whole array
//cells on the ends have single adjacent cell, so the other adjacent cell can be assumsed to be always inactive
if(ind==0){
if(arr[ind+1]==0)
dupArr[ind]=0;
else
dupArr[ind]=1;
}
else if(ind==7){
if(arr[ind-1]==0)
dupArr[ind]=0;
else
dupArr[ind]=1;
}
else{
if((arr[ind-1]==0&&arr[ind+1]==0) || (arr[ind-1]==1&&arr[ind+1]==1)){// if its neighbours are both active or both inactive, the cell becomes inactive the next day
dupArr[ind]=0;
}
else //otherwise it becomes active the next day
dupArr[ind]=1;
}
}
for(ind=0;ind<8;ind++){
arr[ind]=dupArr[ind]; //Copying the altered array to original array, so that we can alter it n number of times.
}
}
for(ind=0;ind<8;ind++)
printf("%d ",arr[ind]);//Displaying output
return 0;
}
Here is my code which i had created some months ago,
You want to create two different arrays, because altering same array element will gives you different results.
func competeCell(cell []uint, days uint) []uint{
n := len(cell)
temp := make([]uint, n)
for i :=0; i < n; i ++ {
temp[i] = cell[i]
}
for days > 0 {
temp[0] = 0 ^ cell[1]
temp[n-1] = 0 ^ cell[n-2]
for i := 1; i < n-2 +1; i++ {
temp[i] = cell[i-1] ^ cell[i +1]
}
for i:=0; i < n; i++ {
cell[i] = temp[i]
}
days -= 1
}
return cell
}
Using c++
#include <list>
#include <iterator>
#include <vector>
using namespace std;
vector<int> cellCompete(int* states, int days)
{
vector<int> result1;
int size=8;
int list[size];
int counter=1;
int i=0;
int temp;
for(int i=0;i<days;i++)//computes upto days
{
vector<int> result;
if(states[counter]==0)
{
temp=0;
list[i]=temp;
//states[i]=0;
result.push_back(temp);
}
else
{
temp=1;
list[i]=temp;
result.push_back(temp);
}
for(int j=1;j<size;j++)
{
if(j==size)
{
if(states[j-1]==0)
{
temp=0;
list[j]=temp;
//states[i]=1;
result.push_back(temp);
}
else
{
temp=1;
list[i]=temp;
//states[i]=1;
result.push_back(temp);
}
}
else if(states[j-1]==states[j+1])
{
temp=0;
list[j]=temp;
//states[i]=1;
result.push_back(temp);
}
else
{
temp=1;
list[j]=temp;
//states[i]=1;
result.push_back(temp);
}
}
result1=result;
for(int i=0;i<size;i++)
{
states[i]=list[i];
}
}
return result1;
}
Java solution
This is solution is Java, which will work any number of Cells and any number of days .
public class Solution
{
public List<Integer> cellCompete(int[] states, int days)
{
List<Integer> inputList = new ArrayList<Integer>();
List<Integer> finalList = new ArrayList<Integer>();
// Covert integer array as list
for (int i :states)
{
inputList.add(i);
}
// for loop for finding status after number of days.
for(int i=1; i<= days; i++)
{
if(i==1)
{
finalList = nextDayStatus(inputList);
}
else
{
finalList = nextDayStatus(finalList);
}
}
return finalList;
}
// find out status of next day, get return as list
public List<Integer> nextDayStatus(List<Integer> input)
{
List<Integer> output = new ArrayList<Integer>();
input.add(0,0);
input.add(0);
for(int i=0; i < input.size()-2; i++)
{
if (input.get(i) == input.get(i+2))
{
output.add(0);
}
else
{
output.add(1);
}
}
return output;
}
}
I know this has been answered, but I gave it a go in Java and am pretty sure it will work for any size states array along with number of days:
public class CellCompete {
public static List<Integer> cellCompete(int[] states, int days) {
List<Integer> resultList = new ArrayList<>();
int active = 1, inactive = 0;
int dayCount = 1;
// Execute for the given number of days
while (days > 0) {
int[] temp = new int[states.length];
System.out.print("Day " + dayCount + ": ");
// Iterate through the states array
for (int i = 0; i < states.length; i++) {
// Logic for first end cell
if (i == 0) {
temp[i] = states[i + 1] == active ? active : inactive;
resultList.add(temp[i]);
System.out.print(temp[i] + ", ");
}
// Logic for last end cell
if (i == states.length - 1) {
temp[i] = states[i - 1] == active ? active : inactive;
resultList.add(temp[i]);
System.out.println(temp[i]);
}
// Logic for the in between cells
if (i > 0 && i < states.length - 1) {
if ((states[i - 1] == active && states[i + 1] == active) || (states[i - 1] == inactive && states[i + 1] == inactive)) {
temp[i] = inactive;
} else {
temp[i] = active;
}
resultList.add(temp[i]);
System.out.print(temp[i] + ", ");
}
}
dayCount++;
days--;
// Reset the states array with the temp array
states = temp;
}
return resultList;
}
public static void main(String[] args) {
int[] states = {1, 1, 0, 1, 0, 1, 0, 0};
int days = 5;
// Total of 40
System.out.println(cellCompete(states, days) );
}
}
Where did the people who wanted optimized solutions go?
def Solution(states, days):
for i in range(days):
for j in range(len(states)):
if (j == 0):
states[i] = states[1]
elif (j == len(states)-1):
states[i] = states[-2]
else:
states[i] = abs(states[i-1] - states[i+1])
return states
By definition, all the cells, including non-existent ones, are in fact booleans:
var cellUpdate = (cells, days) => {
let result = [];
// update states
for(let i = 0; i < cells.length; i++) result.push((!Boolean(cells[i-1]) === !Boolean(cells[i+1])) ? 0 : 1) ;
// repeat for each day
if (days > 1) result = cellUpdate(result, days - 1);
return result;
Here is the best python Solution
value=input()
n=int(input())
lst=[]
for i in value:
if "1"in i:
lst.append(1)
elif "0" in i:
lst.append(0)
for _ in range(n):
store = []
for i in range(8):
if i==0:
store.append(lst[i+1])
elif i==7:
store.append(lst[i-1])
elif lst[i-1]==lst[i+1]:
store.append(0)
else:
store.append(1)
lst=store
print(store)
Scala solution:
def cellDayCompete(cells: Seq[Int]): Seq[Int] = {
val addEdges = 0 +: cells :+ 0
(addEdges.dropRight(2) zip addEdges.drop(2)).map {
case (left, right) =>
(left - right).abs
}
}
def cellCompete(cells: Seq[Int], days: Int): Seq[Int] = {
if (days == 0) {
cells
} else {
cellCompete(cellDayCompete(cells), days - 1)
}
}
A code run with the example above can be found at Scastie
Just answered this question today and here was my solution in python3
def cellCompete(states, days):
for i in range(0, days):
#this is where we will hold all the flipped states
newStates = []
'''
Algo: if neigbors are the same, append 0 to newStates
if they are different append 1 to newStates
'''
for currState in range(len(states)):
#left and right ptr's
left = currState - 1
right = currState + 1
#if at beginning of states, left is automatically inactive
if left < 0:
if states[right] == 1:
newStates.append(1)
else:
newStates.append(0)
#if at end of states, right is automatically inactive
elif right > 7: #we know there is always only 8 elems in the states list
if states[left] == 1:
newStates.append(1)
else
newStates.append(0)
#check to see if neighbors are same or different
elif states[left] != states[right]:
newStates.append(1)
else:
newStates.append(0)
#Set the states equal to the new flipped states and have it loop N times to get final output.
states = newStates
return states
def cellCompete(states, days):
d = 0
l = len(states)
while d < days:
new_states = [0] * l
for i in range(l):
if i == 0 and states[i+1] == 0 or i == l - 1 and states[i-1] == 0:
new_states[i] = 0
elif i == 0 and states[i+1] == 1 or i == l - 1 and states[i-1] == 1:
new_states[i] = 1
elif states[i+1] == states[i-1]:
new_states[i] = 0
else:
new_states[i] = 1
states = new_states
d = d + 1
return states
static int[] CellCompete(int[] states, int days)
{
int e = states.Length;
int[] newStates = new int[(e+2)];
newStates[0] = 0;
newStates[e+1] = 0;
Array.Copy(states, 0, newStates, 1, e);
for (int d = 0; d < days; d++)
{
states = Enumerable.Range(1, e).Select(x => newStates[x - 1] ^ newStates[x + 1]).ToArray();
newStates[0] = 0;
newStates[e + 1] = 0;
Array.Copy(states, 0, newStates, 1, e);
}
return states;
}
//Here is a working solution for this problem in C#
public class HousesinSeq
{
private string _result;
public string Result
{
get { return _result; }
}
public void HousesActivation(string houses, int noOfDays)
{
string[] housesArr = houses.Split(' ');
string[] resultArr = new string[housesArr.Length];
for (int i = 0; i < noOfDays; i++)
{
for (int j = 0; j < housesArr.Length; j++)
{
if (j == 0)
{
if (housesArr[j + 1] == "0")
{
resultArr[j] = "0";
}
else
{
resultArr[j] = "1";
}
}
else if (j == housesArr.Length - 1)
{
if (housesArr[j - 1] == "0")
{
resultArr[j] = "0";
}
else
{
resultArr[j] = "1";
}
}
else
{
if (housesArr[j + 1] == housesArr[j - 1])
{
resultArr[j] = "0";
}
else
{
resultArr[j] = "1";
}
}
}
resultArr.CopyTo(housesArr, 0);
}
foreach (var item in resultArr)
{
//Console.Write($"{item} ");
_result += item + " ";
}
_result = _result.Trim();
}
}
public class Colony {
public static int[] cellCompete(int[] cell, int day) {
int[] ar = new int[10];
for(int i=1; i<9; i++) {
ar[i] = cell[i-1];
}
while(day-- >0) {
int temp = 0;
for(int i=1; i<9; i++) {
if(Math.abs(temp-ar[i+1])==1) {
temp = ar[i];
ar[i] = 1;
}
else {
temp = ar[i];
ar[i] = 0;
}
}
}
return ar;
}
public static void main(String[] args) {
int[] cell = {1,0,1,1,0,1,0,1};
int day = 1;
cell = cellCompete(cell, day);
for(int i=1; i<9; i++) {
System.out.print(cell[i]+" ");
}
}
}

8051 microcontroller lcd countdown timer

Currently i faced some problem on my lcd screen. I'm try to do a countdown timer but when i set Hour = 0, Min = 1, the sec hit 0 and my hour turn to some unknown character and min = 59, sec = 59. I'm i missing out something?
void Timer1(void) interrupt 3
{
TF1 = 0;
TH1 = 0xB1;
TL1 = 0XE0;
cd_msec--;
if(cd_msec == 0)
{
cd_msec = 99;
cd_sec--;
}
if(cd_sec == 0)
{
cd_sec = 59;
cd_min--;
}
if(cd_min == 0)
{
cd_min = 59;
cd_hour--;
}
if(cd_hour == 0)
{
cd_hour = 0;
}
if(cd_hour == 0 && cd_min == 0)
{
cd_hour = 0;
cd_min = 0;
}
if(cd_hour == 0 && cd_min == 0 && cd_sec == 0)
{
cd_hour = 0;
cd_min = 0;
cd_sec = 0;
cd_msec = 0;
}
}
I agree with #nielsen that the logic is wrong. You may consider following approach to update all the variables properly at every millisecond tick.
Also, I have assigned milli_sec to 999 considering that you will manage to get a 16 bit variable for it.
if (milli_sec > 0)
{
milli_sec--
} else {
if (second > 0) {
milli_sec = 999;
second--;
} else {
if (minute > 0) {
milli_sec = 999;
second = 59
minute--
} else {
if (hour > 0) {
milli_sec = 999;
second = 59;
minute = 59;
hour--
}
else {
//COUNTDOWN REACHED TO 0
//hour,minute,second,milli_second is zero
}
}
}
}
Your logic is pretty wrong.
Assume the pre-condition:
cd_msec=1; cd_sec=1; cd_min=5;
When the code executes, you'll get:
cd_msec=99; cd_sec=59; cd_min=4;
So a single tick changed the countdown more than 1 sec.
Remember that zero is a valid value! I'll suggest that you rewrite the code so that you check for zero before decrementing.
Something like:
if (cd_msec > 0) {
cd_msec--;
}
else
{
if (cd_sec > 0) {
cd_sec--;
cd_msec = 99; // Assummes 10ms ticks
}
else
{
// Handle case with both cd_msec and cd_sec being zero
// ...
// ....
}
}
You have 0H : 1M : 0S.
You check seconds, seconds is zero. You set minutes = 0.
You check minutes, it is now 0. So you subtract 1 from hours. Hours is already zero. So it wraps around to maybe ~65k.
IMHO it would be better to have only msecs and convert to hours:minutes:seconds only when you update the display (if you need).

Resources