How my character stays near a block? - graphics

I have a problem with block/wall detection:
red = character
green = block/wall
Attempt: When my character touches e.g. a block/wall on the left side it should stay on the left side.
int len = blocks.size();
for (int b = 0; b < len; b++) {
Block block = block.get(i);
Rectangle r1 = red.bounds;
Rectangle r2 = block.bounds;
if((r1.lowerLeft.y + r1.height/2) > (r2.lowerLeft.y - r2.height/2)) {
...
}
if((r1.lowerLeft.y - r1.height/2) < (r2.lowerLeft.y + r2.height/2)) {
...
}
if((r1.lowerLeft.x + r1.width/2) > (r2.lowerLeft.x - r2.width/2)) {
...
}
if((r1.lowerLeft.x - r1.width/2) < (r2.lowerLeft.x + r2.width/2)) {
...
}
}

It seems as if you just had to mingle the code.
Your condition to find out if its on the top then computes what had to be done if it was on the bottom. Just exchange the code inside the conditions and you're good to go, i guess!

Related

Palindrome operations on a string

You are given a string S initially and some Q queries. For each query you will have 2 integers L and R. For each query, you have to perform the following operations:
Arrange the letters from L to R inclusive to make a Palindrome. If you can form many such palindromes, then take the one that is lexicographically minimum. Ignore the query if no palindrome is possible on rearranging the letters.
You have to find the final string after all the queries.
Constraints:
1 <= length(S) <= 10^5
1 <= Q <= 10^5
1<= L <= R <= length(S)
Sample Input :
4
mmcs 1
1 3
Sample Output:
mcms
Explanation:
The initial string is mmcs, there is 1 query which asks to make a palindrome from 1 3, so the palindrome will be mcm. Therefore the string will mcms.
If each query takes O(N) time, the overall time complexity would be O(NQ) which will give TLE. So each query should take around O(logn) time. But I am not able to think of anything which will solve this question. I think since we only need to find the final string rather than what every query result into, I guess there must be some other way to approach this question. Can anybody help me?
We can solve this problem using Lazy Segment Tree with range updates.
We will make Segment Tree for each character , so there will be a total of 26 segment trees.
In each node of segment tree we will store the frequency of that character over the range of that node and also keep a track of whether to update that range or not.
So for each query do the following ->
We are given a range L to R
So first we will find frequency of each character over L to R (this will take O(26*log(n)) time )
Now from above frequencies count number of characters who have odd frequency.
If count > 1 , we cannot form palindrome, otherwise we can form palindrome
If we can form palindrome then,first we will assign 0 over L to R for each character in Segment Tree and then we will start from smallest character and assign it over (L,L+count/2-1) and (R-count/2+1,R) and then update L += count/2 and R -= count/2
So the time complexity of each query is O(26log(n)) and for building Segment Tree time complexity is O(nlog(n)) so overall time complexity is O(nlogn + q26logn).
For a better understanding please see my code,
#include <bits/stdc++.h>
using namespace std;
#define enl '\n'
#define int long long
#define sz(s) (int)s.size()
#define all(v) (v).begin(),(v).end()
#define input(vec) for (auto &el : vec) cin >> el;
#define print(vec) for (auto &el : vec) cout << el << " "; cout << "\n";
const int mod = 1e9+7;
const int inf = 1e18;
struct SegTree {
vector<pair<bool,int>>lazy;
vector<int>cnt;
SegTree () {}
SegTree(int n) {
lazy.assign(4*n,{false,0});
cnt.assign(4*n,0);
}
int query(int l,int r,int st,int en,int node) {
int mid = (st+en)/2;
if(st!=en and lazy[node].first) {
if(lazy[node].second) {
cnt[2*node] = mid - st + 1;
cnt[2*node+1] = en - mid;
}
else {
cnt[2*node] = cnt[2*node+1] = 0;
}
lazy[2*node] = lazy[2*node+1] = lazy[node];
lazy[node] = {false,0};
}
if(st>r or en<l) return 0;
if(st>=l and en<=r) return cnt[node];
return query(l,r,st,mid,2*node) + query(l,r,mid+1,en,2*node+1);
}
void update(int l,int r,int val,int st,int en,int node) {
int mid = (st+en)/2;
if(st!=en and lazy[node].first) {
if(lazy[node].second) {
cnt[2*node] = mid - st + 1;
cnt[2*node+1] = en - mid;
}
else {
cnt[2*node] = cnt[2*node+1] = 0;
}
lazy[2*node] = lazy[2*node+1] = lazy[node];
lazy[node] = {false,0};
}
if(st>r or en<l) return;
if(st>=l and en<=r) {
cnt[node] = (en - st + 1)*val;
lazy[node] = {true,val};
return;
}
update(l,r,val,st,mid,2*node);
update(l,r,val,mid+1,en,2*node+1);
cnt[node] = cnt[2*node] + cnt[2*node+1];
}
};
void solve() {
int n;
cin>>n;
string s;
cin>>s;
vector<SegTree>tr(26,SegTree(n));
for(int i=0;i<n;i++) {
tr[s[i]-'a'].update(i,i,1,0,n-1,1);
}
int q;
cin>>q;
while(q--) {
int l,r;
cin>>l>>r;
vector<int>cnt(26);
for(int i=0;i<26;i++) {
cnt[i] = tr[i].query(l,r,0,n-1,1);
}
int odd = 0;
for(auto u:cnt) odd += u%2;
if(odd>1) continue;
for(int i=0;i<26;i++) {
tr[i].update(l,r,0,0,n-1,1);
}
int x = l,y = r;
for(int i=0;i<26;i++) {
if(cnt[i]/2) {
tr[i].update(x,x+cnt[i]/2-1,1,0,n-1,1);
tr[i].update(y-cnt[i]/2+1,y,1,0,n-1,1);
x += cnt[i]/2;
y -= cnt[i]/2;
cnt[i]%=2;
}
}
for(int i=0;i<26;i++) {
if(cnt[i]) {
tr[i].update(x,x,1,0,n-1,1);
}
}
}
string ans(n,'a');
for(int i=0;i<26;i++) {
for(int j=0;j<n;j++) {
if(tr[i].query(j,j,0,n-1,1)) {
ans[j] = (char)('a'+i);
}
}
}
cout<<ans<<enl;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int testcases = 1;
cin>>testcases;
while(testcases--) solve();
return 0;
}

Connect 4 - C++: Unable to get program to determine whether a win has occurred diagonally

/* The program for the connect 4 gameboard currently follows as the code beneath. The source code represents the initial player as an odd number that is increased by 1, following the second player's move, which is noted under an even number. I am not certain on the manner to get it to detect a win when there are four consecutive odd or even numbers in a diagonal direction. The issue may stem to the use of "if (iswin())" and "winflag = true" in that winflag is never deemed true, however, am not certain.
*/
#include <iostream>
using namespace std;
/*global constants and variables;
*/
const int H = 6;
const int W = 7;
int height = H;
int width = W;
int colstatus[W]; // 1-D keeps tracking which row will be next available spot for each col.
int board[H][W]; // 2-D array
int steps = 0;
int lastcol;
bool winflag = false;
int neighbourrowpos;
int neighbourcolpos;
// function prototypes
int whichside(int, int);
void initialize();
bool islegal(int, int);
bool play();
bool iswin();
void showgame();
int main();
// implementation of functions
bool islegal(int row, int col)
{
if (row<0 || row >= H || col<0 || col>W) return false; // out of boundary of the board.
else
return true;
}
int whichside(int row, int col)
{
if (board[row][col] == 0) return 0; // means a spot is open
if (board[row][col] % 2) return 1; // means odd side
else return -1; // means even side
}
bool iswin()
{
int counter = 1;
int lastrow;
lastrow = colstatus[lastcol] + 1; // based on the next available one to determine the row of the last move.
// vertically, the board should be checked solely in a downward direction, not upward
neighbourrowpos = lastrow + 1; // the first one right after the last move.
neighbourcolpos = lastcol;
while (islegal(neighbourrowpos, neighbourcolpos))
{
//if the stone at nextposition is on the same side of the last drop.
if (whichside(neighbourrowpos, neighbourcolpos) == whichside(colstatus[lastcol] + 1, lastcol))
{
counter++;
if (counter == 4) return true; // win
else
neighbourrowpos++; // ++ to go down
}
else
return false; // no win occurs due to the encounter of of another side before reaching 4.
}
// check horizontally, both left and right
counter = 1; // resets counter to 1 from the last move to check horizontal
//check left first.
neighbourrowpos = lastrow;
neighbourcolpos = lastcol - 1;
while (islegal(neighbourrowpos, neighbourcolpos))
{
if (whichside(neighbourrowpos, neighbourcolpos) == whichside(lastrow, lastcol))
{
counter++;
if (counter == 4) return true; // win
else
neighbourcolpos--; //-- to go left
}
else
break; // too early to return false because the right side may contribute too. The loop should have a break so as to permit the user to continue testing on the right side.
}
// the program will continue to perform a check on the right wing from the previous move.
neighbourcolpos = lastcol + 1;
while (islegal(neighbourrowpos, neighbourcolpos))
{
if (whichside(neighbourrowpos, neighbourcolpos) == whichside(lastrow, lastcol))
{
counter++;
if (counter == 4) return true; // win
else
neighbourcolpos++; //++ to go right
}
else
return false; // when the program has been checked on its left and right sides and meet a different side before reaching 4, which signifies that it can return.
}
//in this stance, the program should check diagonally topleft to bottomright. once more, ensure that two segments are symmetric with respect to the previous move.
neighbourrowpos = lastcol;
neighbourcolpos = lastrow - 1;
while (islegal(neighbourrowpos, neighbourcolpos))
{
if (whichside(neighbourrowpos, neighbourcolpos) == whichside(lastrow, lastcol))
{
counter++;
if (counter == 4) return true; //win
else
neighbourcolpos--; //-- to shift to the left
}
else
return false;
}
neighbourcolpos = lastrow + 1;
while (islegal(neighbourrowpos, neighbourcolpos))
{
if (whichside(neighbourrowpos, neighbourcolpos) == whichside(lastrow, lastcol))
{
counter++;
if (counter == 4) return true; // winner
else
neighbourcolpos++; //++ to shift to the right
}
else return false;
}
counter = 1;
neighbourrowpos = lastrow - 1;
neighbourcolpos = lastcol - 1;
neighbourrowpos = lastrow + 1;
neighbourcolpos = lastcol + 1;
//check diagonally top-right to bottomleft
counter = 1;
neighbourrowpos = lastrow + 1; //conducts a check on the lower left portion of the board
neighbourcolpos = lastcol - 1;
neighbourrowpos = lastrow - 1; //performs a check on the upper right segment of the board
neighbourcolpos = lastcol + 1;
return false;
}
bool play()
{
cout << "Input column number (0-6): ";
cin >> lastcol;
if (lastcol<0 || lastcol >= W) return false;
if (colstatus[lastcol] > -1)
{
board[colstatus[lastcol]][lastcol] = ++steps; // increase step by 1 to maintain counter of the amount of moves. Step has been initialized at zero.
colstatus[lastcol]--;
showgame();
if (iswin()) //This may be the issue, however, am not certain
winflag = true;
return true;
}
else
{
return false;
}
}
void initialize()
{
for (int col = 0; col<W; col++)
colstatus[col] = H - 1;
for (int row = 0; row<H; row++)
for (int col = 0; col<W; col++)
board[row][col] = 0;
}
void showgame()
{
for (int row = 0; row < H; row++)
{
for (int col = 0; col < W; col++)
cout << board[row][col] << "\t";
cout << endl;
}
cout << "---------------------------------------------" << endl;
for (int col = 0; col<W; col++)
cout << colstatus[col] << "\t";
cout << endl;
}
int main()
{
initialize();
showgame();
do
{
do {
bool f = play(); // call play until it is true;
if (f == false)
cout << "You pick a wrong column. Please try again";
else
break; // if it is a legal move, check winflag
} while (true);
if (winflag == true)
{
cout << whichside(colstatus[lastcol] + 1, lastcol) << " win!" << endl; // -1 even side, 1 odd side
break;
}
else
{
// something must be included here but am not certain on the specific statement
}
} while (true);
return 0;
}
This is just a general suggestion to how to check for wins in connect four. Consider that there are 4 ways to win: Horizontal, Vertical, Left Diagonal, and Right Diagonal. You could iterate over the entire board and at each cell that contains a game piece you could do a breadth first search. This would actually need to be 4 versions of the search, one for each way to win. Another constraint that is common to all of the searches: only consider cells that contain the same type of game piece. When searching keep track of the number of steps traveled. Once you have successfully traveled 4 steps, there is a win. This also assumes that you will use some data structure for cycle detection.
With that said the Diagonal versions of the search would only consider cells on their immediate respective corners. For instance the Left Diagonal search with a starting cell of (2,1) would consider the following:[(1, 2), (3, 0)], assuming that (0, 0) is the top left corner of the board.

I want to track 2 colours, but only record the movement of those two colours and hide the video feed

For context: I am going to analyze the breathing movement of parents during kangaroo mother care and I wish to respect their privacy by not recording them, but only the movement of stickers I placed on their chest and stomach.
So far, I'm able to track 2 colours based on webcam input through the code below. However, I would like to record only the tracked colours instead of the webcam feed as to preserve the privacy of the parent.
Does anybody know how to add a background colour, whilst still being able to track colour?
import processing.video.*;
Capture video;
final int TOLERANCE = 20;
float XRc = 0;// XY coordinate of the center of the first target
float YRc = 0;
float XRh = 0;// XY coordinate of the center of the second target
float YRh = 0;
int ii=0; //Mouse click counter
color trackColor; //The first color is the center of the robot
color trackColor2; //The second color is the head of the robot
void setup() {
size(640,480);
video = new Capture(this,640,480);
video.start();
trackColor = color(255,0,0);
trackColor2 = color(255,0,0);
smooth();
}
void draw() {
background(0);
if (video.available()) {
video.read();
}
video.loadPixels();
image(video,0,0);
float r2 = red(trackColor);
float g2 = green(trackColor);
float b2 = blue(trackColor);
float r3 = red(trackColor2);
float g3 = green(trackColor2);
float b3 = blue(trackColor2);
int somme_x = 0, somme_y = 0;
int compteur = 0;
int somme_x2 = 0, somme_y2 = 0;
int compteur2 = 0;
for(int x = 0; x < video.width; x++) {
for(int y = 0; y < video.height; y++) {
int currentLoc = x + y*video.width;
color currentColor = video.pixels[currentLoc];
float r1 = red(currentColor);
float g1 = green(currentColor);
float b1 = blue(currentColor);
if(dist(r1,g1,b1,r2,g2,b2) < TOLERANCE) {
somme_x += x;
somme_y += y;
compteur++;
}
else if(compteur > 0) {
XRc = somme_x / compteur;
YRc = somme_y / compteur;
}
if(dist(r1,g1,b1,r3,g3,b3) < TOLERANCE) {
somme_x2 += x;
somme_y2 += y;
compteur2++;
}
else if(compteur2 > 0) {
XRh = somme_x2 / compteur2;
YRh = somme_y2 / compteur2;
}
}
}
if(XRc != 0 || YRc != 0) { // Draw a circle at the first target
fill(trackColor);
strokeWeight(0.05);
stroke(0);
ellipse(XRc,YRc,20,20);
}
if(XRh != 0 || YRh != 0) {// Draw a circle at the second target
fill(trackColor2);
strokeWeight(0.05);
stroke(0);
ellipse(XRh,YRh,20,20);
}
}
void mousePressed() {
if (mousePressed && (mouseButton == RIGHT)) { // Save color where the mouse is clicked in trackColor variable
if(ii==0){
if (mouseY>480){mouseY=0;mouseX=0;}
int loc = mouseX + mouseY*video.width;
trackColor = video.pixels[loc];
ii=1;
}
else if(ii==1){
if (mouseY>480){mouseY=0;mouseX=0;}
int loc2 = mouseX + mouseY*video.width;
trackColor2 = video.pixels[loc2];
ii=2;
}
}
}
Try adding the background(0); right before you draw the first circle. It should cover the video and you can draw the circles on top of it.
Regards
Jose

Algorithm for finding continuous repeated sequences

I'm looking for an algorithm that finds short tandem repeats in a genome sequence.
Basically, given a really long string which can only consist of the 4 characters 'ATCG', I need to find short repeats between 2-5 characters long that are next to each other.
ex:
TACATGAGATCATGATGATGATGATGGAGCTGTGAGATC
would give ATGATGATG or ATG repeated 3 times
The algorithm needs to scale up to a string of 1 million characters so I'm trying to get as close to linear runtime as possible.
My current algorithm:
Since the repeats can be 2-5 characters long, I check the string character by character and see if the Nth character is the same as the N+Xth character, with X being 2 through 5. With a counter for each X that counts sequential matches and resets at a mismatch, we know if there is a repeat when X = the counter. The subsequent repeats can then be checked manually.
You are looking at each character which gives you O(n), since you compare on each character the next (maximum) five characters this gives you a constant c:
var data = get_input();
var compare = { `A`, `T`, `G`, `A`, `T` } // or whatever
var MAX_LOOKAHEAD = compare.length
var n
var c
for(n = data_array.length; n < size; i++) { // Has runtime O(n)
for(c = 0; c < MAX_LOOKAHEAD; c++) { // Maximum O(c)
if( compare[c] != data[i+c] ) {
break;
} else {
report( "found match at position " + i )
}
}
}
It is easy to see that this runs O(n*c) times. Since c is very small it can be ignored - and I think one can not get rid of that constant - which results in a total runtime of O(n).
The good news:
You can speed this up with parallelization. E.g. you could split this up in k intervals and let multiple threads do the job for you by giving them appropriate start and end indices. This could give you a linear speedup.
If you do that make sure that you treat the intersections as special cases since you could miss a match if your intervals split a match in two.
E.g. n = 50000:
Partition for 4 threads: (n/10000) - 1 = 4. The 5th thread won't have a lot to do since it just handles the intersections which is why we don't need to consider its (in our case tiny) overhead.
1 10000 20000 40000 50000
|-------------------|-------------------|-------------------|-------------------|
| <- thread 1 -> | <- thread 2 -> | <- thread 3 -> | <- thread 4 -> |
|---| |---| |---|
|___________________|___________________|
|
thread 5
And this is how it could look like:
var data;
var compare = { `A`, `T`, `G`, `A`, `T` };
var MAX_LOOKAHEAD = compare.length;
thread_function(args[]) {
var from = args[0];
var to = args[1];
for(n = from ; n < to ; i++) {
for(c = 0; c < MAX_LOOKAHEAD; c++) {
if( compare[c] != data[i+c] ) {
break;
} else {
report( "found match at position " + i )
}
}
}
}
main() {
var data_size = 50000;
var thread_count = 4;
var interval_size = data_size / ( thread_count + 1) ;
var tid[]
// This loop starts the threads for us:
for( var i = 0; i < thread_count; i++ ) {
var args = { interval_size * i, (interval_size * i) + interval_size };
tid.add( create_thread( thread_function, args ) );
}
// And this handles the intersections:
for( var i = 1; i < thread_count - 1; i++ ) {
var args = { interval_size * i, (interval_size * i) + interval_size };
from = (interval_size * i) - compare.length + 1;
to = (interval_size * i) + compare.length - 1;
for(j = from; j < to ; j++) {
for(k = 0; k < MAX_LOOKAHEAD; k++) {
if( compare[k] != data[j+k] ) {
break;
} else {
report( "found match at position " + j )
}
}
}
}
wait_for_multiple_threads( tid );
}

Conways's Game of life array problems

I'm writing a Conway's life game for school. In the program I am having trouble with the arrays taking the values I am assigning them. At one point in the program they print out the value assigned to them (1) yet at the end of the program when I need to print the array to show the iterations of the game it shows an incredibly low number. The other trouble was I was encountering difficulties when putting in a loop that would ask if it wants you to run another iteration. So I removed it until the previous errors were fixed.
Im writing this with C++
#include <stdio.h>
int main (void)
{
int currentarray [12][12];
int futurearray [12][12];
char c;
char check = 'y';
int neighbors = 0;
int x = 0; // row
int y = 0; //column
printf("Birth an organism will be born in each empty location that has exactly three neighbors.\n");
printf("Death an organism with four or more organisms as neighbors will die from overcrowding.\n");
printf("An organism with fewer than two neighbors will die from loneliness.\n");
printf("Survival an organism with two or three neighbors will survive to the next generation.\n");
printf( "To create life input x, y coordinates.\n");
while ( check == 'y' )
{
printf("Enter x coordinate.\n");
scanf("%d", &x ); while((c = getchar()) != '\n' && c != EOF);
printf("Enter y coordinate.\n");
scanf("%d", &y ); while((c = getchar()) != '\n' && c != EOF);
currentarray [x][y] = 1;
printf ("%d\n", currentarray[x][y]);
printf( "Do you wish to enter more input? y/n.\n");
scanf("%c", &check); while((c = getchar()) != '\n' && c != EOF);
}
// Note - Need to add a printf statement showing the array before changes are made after input added.
// check for neighbors
while(check == 'y')
{
for(y = 0; y <= 12; y++)
{
for(x = 0; x <= 12; x++)
{
//Begin counting number of neighbors:
if(currentarray[x-1][y-1] == 1) neighbors += 1;
if(currentarray[x-1][y] == 1) neighbors += 1;
if(currentarray[x-1][y+1] == 1) neighbors += 1;
if(currentarray[x][y-1] == 1) neighbors += 1;
if(currentarray[x][y+1] == 1) neighbors += 1;
if(currentarray[x+1][y-1] == 1) neighbors += 1;
if(currentarray[x+1][y] == 1) neighbors += 1;
if(currentarray[x+1][y+1] == 1) neighbors += 1;
//Apply rules to the cell:
if(currentarray[x][y] == 1 && neighbors < 2)
futurearray[x][y] = 0;
else if(currentarray[x][y] == 1 && neighbors > 3)
futurearray[x][y] = 0;
else if(currentarray[x][y] == 1 && (neighbors == 2 || neighbors == 3))
futurearray[x][y] = 1;
else if(currentarray[x][y] == 0 && neighbors == 3)
futurearray[x][y] = 1;
}
}
}
// Set the current array to the future and change the future to 0
{
for(y = 0; y < 12; y++)
{
for(x = 0; x < 12; x++)
{
//Begin the process
currentarray [x][y] = futurearray [x][y];
futurearray [x][y] = 0;
}
}
}
{
for(y = 0; y < 12; y++)
{
for(x = 0; x < 12; x++)
{
//print the current life board
printf("%d ", currentarray[x][y]);
}
}
}
// Have gone through one iteration of Life
//Ask to do another iteration
printf("Do you wish to continue y/n?\n");
scanf("%c", &check); while((c = getchar()) != '\n' && c != EOF);
return 0;
}
You are defining your arrays as [12][12].
In your generation loop you walk from i = 0 to i <= 12, which is 13 steps instead of the 12 of the array. Additionally you are trying to access x-1 and y-1, which can be as low as -1. Again not inside your array.
Sometimes you get semi-useful values from within your array, but on some borders you are just accessing random data.
Try to correct your border.
You forgot to set neighbors to 0 before counting them.
Since this is C++ (not C), you might as well declare neighbors inside the loop body. Makes these kinds of issues easier to spot, too.
Also, is it me, or is that while loop never going to finish? Your braces are a mess, in general, as is your indentation. You could do yourself and us a favour by cleaning those up.
Obviously agree with all the above suggestions. One nice trick you might want to implement with Life is to create an extra border around your area. So if the user wants a 12x12 grid (and you should allow width/height to be specified and allocate memory dynamically) internally you hold a 14x14 grid corresponding to a border around the actual grid. Before running the calculation copy the top row to the bottom border, bottom row to the top border etc. Now you can run the main algorithm on the inner 12x12 grid without worrying about edge cases. This will enable your patterns to re-appear on the other side if they fall off the edge.
You're also forgetting to set the values of both arrays to zero. This will take care of the ridiculous number issue you're having. you can do that by copying this for loop:
for(y = 0; y < 12; y++)
{
for(x = 0; x < 12; x++)
{
//Begin the process
currentarray [x][y] = futurearray [x][y];
futurearray [x][y] = 0;
}
}
and pasting it before the while loop but instead of setting currentarray[x][y] = futurearray[x][y], set it to 0. Also, if the coordinates are viewable locations instead of array co-ordinates, you'll want to change this:
printf ("%d\n", currentarray[x][y]);
to this:
printf ("%d\n", currentarray[x-1][y-1]);
I would also recommend putting a printf with a newline (\n) after each row has been printed and a tab (\t) after each item so that the formatting looks cleaner.

Resources