I'm working on a numerical simulation program, for simplicity I recreated the code into expanding circles on a domain bounded on each side. I want to track each circle's radius. If I have this code:
int const N = 10;
int D[N+2][N+2]; //domain bounded on each side
int const nCircle = 4;
int center[nCircle][2] = {{1, 1}, {N, N}, {N, 1}, {1, N}};
void eval(); //function to expand circles
int main() {
for (int n=0;n<5;n++) {
eval();
for (int y=1;y<=N;y++) {
for (int x=1;x<=N;x++) {
printf("%d ", D[x][y]);
}
printf("\n");
}
printf("\n");
}
}
for visualization and simplicity purpose,
add these into global definition
double radius[nCircle] = {2, 2, 2, 2}; //actually unknown, i want to track this
void eval() {
double a;
for (int z=0;z<nCircle;z++) {
for (int y=1;y<=N;y++) {
for (int x=1;x<=N;x++) {
a = pow(x-center[z][0], 2) + pow(y-center[z][1], 2);
if (a <= pow(radius[z], 2))
D[x][y] = 1;
}
}
radius[z] += ((double) rand() / (RAND_MAX));
}
}
How do I do that?
edit:
note that circles might overlap each other, array D only store the union of circle area without information of the intersections.
Cannot declare a global array with a variable size (VLA). Use a compile time constant.
// int const N = 10;
#define N 10
int D[N+2][N+2];
// int const nCircle = 4;
#define nCircle 4
int center[nCircle][2] = {{1, 1}, {N, N}, {N, 1}, {1, N}};
double radius[nCircle] = {2, 2, 2, 2};
Alternatively use C99, and declare D[] and center[] inside main(). Code could use another method to use data in eval() like eval(N, D, nCircle, center, radius)
int main() {
int const N = 10;
int D[N+2][N+2] = {0}; // Initialize D
int const nCircle = 4;
int center[nCircle][2] = {{1, 1}, {N, N}, {N, 1}, {1, N}};
double radius[nCircle] = {2, 2, 2, 2};
Related
I have an mainFun that takes four parameters x, a, b, and c, all vector-valued and possibly of varying length. This function calls expensiveFun that is computationally expensive so I'd like to reduce the number of calls to expensiveFun. This function needs to be called for each value in x[i], a[i], b[i], c[i] and if a, b, or c are of shorter length, then they need to be "wrapped" (their index is in modulo a[i % a.size()]). It would be the best to precompute the expensiveFun for each possible distinct value of x (i.e. all integers 0,...,max(x)) and then just fill-in the output out by out[i] = precomputedValues[x[i]]. This can be easily achieved if a, b, and c have the same length (example below), but it gets ugly if they are not. Is there any way to make it more efficient for case when the lengths of parameter vectors differ?
Below I provide a reproducible example. It's a simplified code, written just to serve as example.
std::vector<int> expensiveFun(int x, int a, int b, int c) {
std::vector<int> out(x+1);
out[0] = a+b*c;
for (int i = 1; i <= x; i++)
out[i] = out[i-1] * i + a * (b+c);
return out;
}
std::vector<int> mainFun(
std::vector<int> x,
std::vector<int> a,
std::vector<int> b,
std::vector<int> c
) {
int n = x.size();
int a_size = a.size();
int b_size = b.size();
int c_size = c.size();
std::vector<int> out(n);
// easy
if (a_size == b_size && b_size == a_size) {
int max_x = 0;
for (int j = 0; j < n; j++)
if (x[j] > max_x)
max_x = x[j];
for (int i = 0; i < a_size; i++) {
int max_x = 0;
for (int j = 0; j < n; j += a_size) {
if (x[j] > max_x)
max_x = x[j];
}
std::vector<int> precomputedValues = expensiveFun(max_x, a[i], b[i], c[i]);
for (int j = i; j < n; j += a_size) {
out[j] = precomputedValues[x[j]];
}
}
// otherwise give up
} else {
for (int j = 0; j < n; j++) {
out[j] = expensiveFun(x[j], a[j % a_size], c[j % c_size], c[j % c_size]).back();
}
}
return out;
}
Example input:
x = {0, 1, 5, 3, 2, 1, 0, 4, 4, 2, 3, 4, 1}
a = {1, 2, 3}
b = {1, 2}
c = {3, 4, 5, 6}
Parameters should be folded so that they become:
x = {0, 1, 5, 3, 2, 1, 0, 4, 4, 2, 3, 4, 1}
a = {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1}
b = {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1}
c = {3, 4, 5, 6, 3, 4, 5, 6, 3, 4, 5, 6, 3}
The output is not important at the moment since the main issue in here is about efficiently dealing with varying-size parameter vectors.
Memoize your function.
Once you compute a vector for a combination of a, b, and c, store it in an std::unordered_map. The next time you see the same combination, you retrieve the vector that you have already computed - the classic approach of paying with computer memory for computation speed-up.
std::map<std::tuple<int,int,int>,std::vector<int>> memo;
int expensiveFunMemo(int x, int xMax, int a, int b, int c) {
assert(x <= xMax);
std::vector<int>& out = memo[std::make_tuple(a, b, c)];
if (!out.size()) {
out.push_back(a+b*c);
for (int i = 1; i <= xMax; i++)
out.push_back(out[i-1] * i + a * (b+c));
}
assert(out.size == xMax+1);
return out[x];
}
This way you would never compute expensiveFunMemo for any combination of {a, b, c} more than once.
Your mainFun becomes simpler, too:
std::vector<int> mainFun(
const std::vector<int>& x,
const std::vector<int>& a,
const std::vector<int>& b,
const std::vector<int>& c
) {
size_t n = x.size();
size_t a_size = a.size();
size_t b_size = b.size();
size_t c_size = c.size();
std::vector<int> out(n);
int xMax = *std::max_element(x.begin(), x.end());
for (size_t j = 0 ; j < n ; j++) {
out[j] = expensiveFunMemo(x[j], xMax, a[j % a_size], c[j % c_size], c[j % c_size]);
}
return out;
}
Note: this solution uses std::map<K,V> instead of std::unordered_map<K,V> because std::tuple<...> lacks a generic hash function. This Q&A offers a solution to fix this problem.
The task is to rotate left or rotate right a subarray of an array given number of times.
Let me explain this on an example:
lets data be an array.
data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
a sub array is determined by parameters begin and end.
if begin = 3 and end = 7, then subarray is {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
if begin = 7 and end = 3, then subarray is {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let's rotate it right two times
if begin = 3 and end = 7, then the result is {0, 1, 2, 6, 7, 3, 4, 5, 8, 9};
if begin = 7 and end = 3, then the result is {8, 9, 0, 1,, 4, 5, 6, 2, 3, 7};
I've written code that performs this task but it's to slow.
Can someone give me a hint how to make it quicker?
Important: I'm not allowed to use other arrays than data, subprograms and build-in functions.
#include <iostream>
using namespace std;
int main(){
int dataLength;
cin >> dataLength;
int data [ dataLength ];
for (int i = 0; i < dataLength; i++){
cin >> data [ i ];
}
int begin;
int end;
int rotation;
int forLoopLength;
int tempBefore;
int tempAfter;
cin >> begin;
cin >> end;
cin >> rotation;
if (end > begin)
forLoopLength = (end - begin) + 1;
else
forLoopLength = (end - begin) + 1 + dataLength;
if (rotation < 0)
rotation = forLoopLength + (rotation % forLoopLength);
else
rotation = rotation % forLoopLength;
for (int i = 0; i < rotation; i++) {
tempBefore = data [ end ];
for (int i = 0; i < forLoopLength; i++) {
tempAfter = data [ (begin + i) % dataLength ];
data [ (begin + i) % dataLength ] = tempBefore;
tempBefore = tempAfter;
}
}
for (int i = 0; i < dataLength; i ++ ) {
cout << data [ i ] << " ";
}
return 0;
}
There's a trick to this. It's pretty weird that you'd get this for homework if the trick wasn't mentioned in class. Anyway...
To rotate a sequence of N elements left by M:
reverse the whole sequence
reverse the last M elements
reverse the first N-M elements
done
e.g. left by 2:
1234567
->
7654321
->
7654312
->
3456712
Here is my code, it makes exactly n reads and n writes, where n is subarray size.
#include<iostream>
int arr[]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// replacing 'addr( pos, from, size )' with just 'pos' mean rotation the whole array
int addr( int ptr, int from, int size)
{
return (ptr + from ) % size;
}
void rotate( int* arr, int shift, int from, int count, int size)
{
int i;
int pos= 0;
int cycle= 0;
int c= 0;
int c_old= 0;
// exactly count steps
for ( i=0; i< count; i++ ){
// rotation of arrays part is essentially a permutation.
// every permutation can be decomposed on cycles
// here cycle processing begins
c= arr[ addr( pos, from, size ) ];
while (1){
// one step inside the cycle
pos= (pos + shift) % count;
if ( pos == cycle )
break;
c_old= c;
c= arr[ addr( pos, from, size ) ];
arr[ addr( pos, from, size ) ]= c_old;
i++;
}
// here cycle processing ends
arr[ addr( pos, from, size ) ]= c;
pos= (pos + 1) % count;
cycle= (cycle + 1) % count;
}
}
int main()
{
rotate( arr, 4, 6, 6, 11 );
int i;
for ( i=0; i<11; i++){
std::cout << arr[i] << " ";
}
std::cout << std::endl;
return 0;
}
I am doing this problem http://community.topcoder.com/stat?c=problem_statement&pm=2915&rd=5853, but my program gives wrong output, I tried more ways and it does not work properly. I do not get it, because other people do it like me and they are fine. Can you please check if I have properly implemented the BFS? Thanks in advance.
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
#define P push
#define PP pop();
#define T front();
int mo[][2] = { {-2, -1}, {-2, 1}, {2, -1}, {2, 1}, {-1, -2}, {1, -2}, {-1, 2}, {1, 2} };
int m[8][8];
int BFS(int sy, int sx, int fy, int fx)
{
queue<int> s;
m[sy][sx] = 1;
s.P(sy);
s.P(sx);
s.P(0);
while(!s.empty())
{
int d = s.T s.PP
int x = s.T s.PP
int y = s.T s.PP
for(int i=0;i < 8;i++)
{
int yy = y + mo[i][0];
int xx = x + mo[i][1];
if(yy < 0 || yy > 7 || xx < 0 || xx > 7) continue;
if(m[yy][xx] != -1) continue;
if(yy == fy && xx == fx) return d + 1;
m[yy][xx] = 0;
s.P(yy);
s.P(xx);
s.P(d+1);
}
}
return -1;
}
class CaptureThemAll {
public:
int fastKnight(string knight, string rook, string queen) {
vector<int> p{knight[0] - 'a', knight[1] - '1', rook[0] - 'a', rook[1] - '1', queen[0] - 'a', queen[1] - '1'};
memset(m, -1, sizeof(m));
int a = BFS(p[1], p[0], p[3], p[2]);
memset(m, -1, sizeof(m));
int b = BFS(p[1], p[0], p[5], p[4]);
memset(m, -1, sizeof(m));
int c = BFS(p[3], p[2], p[5], p[4]);
return min(a,b) + c;
}
};
I think the problem might be that you push y,x,d so your queue will be
Front y Middle x End d
But when you pop the front element you place it (y) into a variable called d.
It may work better if you change:
int d = s.T s.PP
int x = s.T s.PP
int y = s.T s.PP
to
int y = s.T s.PP
int x = s.T s.PP
int d = s.T s.PP
I am converting Matlab code to OpenCV "C/cpp" code. And I have some doubts as below.
A = [ 2; 10; 7; 1; 3; 6; 10; 10; 2; 10];
ind = [10; 5; 9; 2];
B is a submatrix of A ; Elements of matrix B are elements of A at locations specified in ind.
B = [10 3; 2; 10];
In Matlab, I just use
B = A(ind);
In C using OpenCV,
for ( int i = 0; i < ind.rows; i++) {
B.at<int>(i,0) = A.at<int>(ind.at<int>(i,0), 0);
}
Is there a way to do it without using for loop?
If you are looking for an tidy way of copying. I would suggest you define a function
Here is a STL-like implementation of copy at given position
#include<vector>
#include<cstdio>
using namespace std;
/**
* Copies the elements all elements of B to A at given positions.
* indexing array ranges [ind_first, ind_lat)
* e.g
* int A[]= {0, 2, 10, 7, 1, 3, 6, 10, 10, 2, 10};
* int B[] = {-1, -1, -1, -1};
* int ind[] = {10, 5, 9, 2};
* copyat(B, A, &ind[0], &ind[3]);
* // results: A:[0,2,10,7,1,-1,6,10,10,-1,-1]
*/
template<class InputIterator, class OutputIterator, class IndexIterator>
OutputIterator copyat (InputIterator src_first,
OutputIterator dest_first,
IndexIterator ind_first,
IndexIterator ind_last)
{
while(ind_first!=ind_last) {
*(dest_first + *ind_first) = *(src_first);
++ind_first;
}
return (dest_first+*ind_first);
}
int main()
{
int A[]= {0, 2, 10, 7, 1, 3, 6, 10, 10, 2, 10};
int B[] = {-1, -1, -1, -1};
int ind[] = {10, 5, 9, 2};
copyat(B, A, &ind[0], &ind[3]);
printf("A:[");
for(int i=0; i<10; i++)
printf("%d,", A[i]);
printf("%d]\n",A[10]);
}
I want to solve this CodeChef challenge:
Suppose We are given an array A of N(of range 100,000) elements. We are to find the count of all pairs of 3 such elements 1<=Ai,Aj,Ak<=30,000 such that
Aj-Ai = Ak- Aj and i < j < k
In other words Ai,Aj,Ak are in Arithmetic Progression. For instance for Array :
9 4 2 3 6 10 3 3 10
so The AP are:
{2,6,10},{9,6,3},{9,6,3},{3,3,3},{2,6,10}
So the required answer is 5.
My Approach
What I tried is take 30,000 long arrays named past and right. Initially right contains the count of each 1-30,000 element.
If we are at ith position past stores the count of array value before i and right stores the count of array after i. I simply loop for all possible common difference in the array. Here is the code :
right[arr[1]]--;
for(i=2;i<=n-1;i++)
{
past[arr[i-1]]++;
right[arr[i]]--;
k=30000 - arr[i];
if(arr[i] <= 15000)
k=arr[i];
for(d=1;d<=k;d++)
{
ans+= right[arr[i] + d]*past[arr[i]-d] + past[arr[i] + d]*right[arr[i]-d];
}
ans+=past[arr[i]]*right[arr[i]];
}
But this gets me Time Limit Exceeded. Please help with a better algorithm.
You can greatly cut execution time if you make a first pass over the list and only extract number pairs that it is possible to have an 3 term AP between (difference is 0 mod 2). And then iterating between such pairs.
Pseudo C++-y code:
// Contains information about each beginning point
struct BeginNode {
int value;
size_t offset;
SortedList<EndNode> ends; //sorted by EndNode.value
};
// Contains information about each class of end point
struct EndNode {
int value;
List<size_t> offsets; // will be sorted without effort due to how we collect offsets
};
struct Result {
size_t begin;
size_t middle;
size_t end;
};
SortedList<BeginNode> nodeList;
foreach (auto i : baseList) {
BeginNode begin;
node.value = i;
node.offset = i's offset; //you'll need to use old school for (i=0;etc;i++) with this
// baseList is the list between begin and end-2 (inclusive)
foreach (auto j : restList) {
// restList is the list between iterator i+2 and end (inclusive)
// we do not need to consider i+1, because not enough space for AP
if ((i-j)%2 == 0) { //if it's possible to have a 3 term AP between these two nodes
size_t listOffset = binarySearch(begin.ends);
if (listOffset is valid) {
begin.ends[listOffset].offsets.push_back(offsets);
} else {
EndNode end;
end.value = j;
end.offsets.push_back(j's offset);
begin.ends.sorted_insert(end);
}
}
}
if (begin has shit in it) {
nodeList.sorted_insert(begin);
}
}
// Collection done, now iterate over collection
List<Result> res;
foreach (auto node : nodeList) {
foreach (auto endNode : node.ends) {
foreach (value : sublist from node.offset until endNode.offsets.last()) {
if (value == average(node.value, endNode.value)) {
// binary_search here to determine how many offsets in "endNode.offsets" "value's offset" is less than.
do this that many times:
res.push_back({node.value, value, endNode.value});
}
}
}
}
return res;
Here's a simple C version of the solution that takes advantage of the Ai + Ak must be even test:
#include <stdio.h>
static int arr[] = {9, 4, 2, 3, 6, 10, 3, 3, 10};
int main ()
{
int i, j, k;
int sz = sizeof(arr)/sizeof(arr[0]);
int count = 0;
for (i = 0; i < sz - 2; i++)
{
for (k = i + 2; k < sz; k++)
{
int ik = arr[i] + arr[k];
int ikdb2 = ik / 2;
if ((ikdb2 * 2) == ik) // if ik is even
{
for (j = i + 1; j < k; j++)
{
if (arr[j] == ikdb2)
{
count += 1;
printf("{%d, %d, %d}\n", arr[i], arr[j], arr[k]);
}
}
}
}
}
printf("Count is: %d\n", count);
}
and the console dribble:
tmp e$ cc -o triples triples.c
tmp e$ ./triples
{9, 6, 3}
{9, 6, 3}
{2, 6, 10}
{2, 6, 10}
{3, 3, 3}
Count is: 5
tmp e$
This more complicated version keeps a list of Aj indexed by value to go from n-cubed to n-squared (kinda).
#include <stdio.h>
#include <stdint.h>
static uint32_t arr[] = {9, 4, 2, 3, 6, 10, 3, 3, 10};
#define MAX_VALUE 100000u
#define MAX_ASIZE 30000u
static uint16_t index[MAX_VALUE+1];
static uint16_t list[MAX_ASIZE+1];
static inline void remove_from_index (int subscript)
{
list[subscript] = 0u; // it is guaranteed to be the last element
uint32_t value = arr[subscript];
if (value <= MAX_VALUE && subscript == index[value])
{
index[value] = 0u; // list now empty
}
}
static inline void add_to_index (int subscript)
{
uint32_t value = arr[subscript];
if (value <= MAX_VALUE)
{
list[subscript] = index[value]; // cons
index[value] = subscript;
}
}
int main ()
{
int i, k;
int sz = sizeof(arr)/sizeof(arr[0]);
int count = 0;
for (i = 0; i < sz - 2; i++)
{
for (k = i; k < sz; k++) remove_from_index(k);
for (k = i + 2; k < sz; k++)
{
uint32_t ik = arr[i] + arr[k];
uint32_t ikdb2 = ik / 2;
add_to_index(k-1); // A(k-1) is now a legal middle value
if ((ikdb2 * 2) == ik) // if ik is even
{
uint16_t rover = index[ikdb2];
while (rover != 0u)
{
count += 1;
printf("{%d, %d, %d}\n", arr[i], arr[rover], arr[k]);
rover = list[rover];
}
}
}
}
printf("Count is: %d\n", count);
}
and the dribble:
tmp e$ cc -o triples triples.c
tmp e$ ./triples
{9, 6, 3}
{9, 6, 3}
{2, 6, 10}
{2, 6, 10}
{3, 3, 3}
Count is: 5
tmp e$