how to fastly find array which include some numbers(1~255)? - algorithm

I want to solve some algorithm problem.
Could you suggest any algorithms working more fast?
*Problem summary
- Find same array of key[200] is same as source array KEY[200]
- Each element of KEY[200] array is random numbers range 1~255
- only 2 file are given.
- You must implement just function find_array() of user_code.cpp
- It is not allowed to edit any other things
- You can use check() function for finding array
- test case is 50, time limit is 10 sec for 50 test case, memory limit is 256MB.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern void find_array(unsigned char key[200]);
unsigned char KEY[200];
int check(unsigned char key[200])
{
int pos = 0;
int equal = 0;
for (int c = 0; c < 200; c++)
{
if (key[c] == KEY[c])
pos++;
}
for (int c1 = 0; c1 < 200; c1++)
{
for (int c2 = 0; c2 < 200; c2++)
{
if(key[c1] == KEY[c2])
equal++;
}
}
return pos * 256 + equal;
}
int main()
{
for (int t = 0; t < 1; t++) //test case 50개
{
for (int i = 0; i < 200; i++)
{
KEY[i] = rand() % 255 + 1; //1~255
}
unsigned char key[200] = { 0, };
find_array(key); //you must implement this function
}
return 0;
}
//user_code.cpp
extern int check(unsigned char key[200]);
//you must implement this function
//below is my code take a long time(about 2sec for each case)
void find_array(unsigned char key[200])
{
unsigned char temp[200];
int result, pos, equal;
for (int k = 0; k < 200; k++)
temp[k] = 0;
for (int i = 0; i < 200; i++)
{
for (int val = 1; val <= 255; val++)
{
temp[i] = val;
result = check(temp);
equal = result % 256;
pos = (result - equal) / 256;
if (pos >= 1)
{
key[i] = val;
temp[i] = 0;
break;
}
}
}
}

Related

Code just loads for a second, then closes without doing anything

For some reason, whenever I run this code, it just opens; loads for a sec; then closes without doing anything. Whenever I try to narrow it down to a piece of code, it makes absolutely no sense, like the line int dirX.
#include <iostream>
#include <queue>
using namespace std;
void solve()
{
// ENTER CODE BELOW
struct Loc
{
int x, y;
Loc (int xx=0, int yy=0) : x(xx), y(yy) {}
};
int n=0, currX=1002, currY=1002, dx[]={-1,1,0,0},dy[]={0,0,-1,1}; string str=""; bool isFence[2010][2010]; queue<Loc> q;
int ret=-1;
for (int i = 0; i < 2005; i++) {
for (int j = 0; j < 2005; j++) {
isFence[i][j]=false;
}
}
cin >> n >> str;
isFence[currX][currY]=true;
int dirX, dirY;
for (auto i : str)
{
dirX=0; dirY=0;
if (i=='N') dirX=-1;
else if (i=='S') dirX=1;
else if (i=='W') dirY=-1;
else dirY=1;
for (int j = 0; j < 2; j++) {
currX += dirX;
currY += dirY;
isFence[currX][currY]=true;
}
}
Loc curr; int nx, ny;
for (int i = 0; i < 2005; i++)
{
for (int j = 0; j < 2005; j++)
{
cout << isFence[i][j] << endl;
if (isFence[i][j]) continue;
ret++;
q = std::queue<Loc>();
q.push(Loc(i,j));
isFence[i][j]=true;
while (!q.empty())
{
curr = q.front(); q.pop();
for (int k = 0; k < 4; k++) {
nx = curr.x+dx[k]; ny=curr.y+dy[k];
if (nx >= 0 && nx < 2005 && ny >= 0 && ny<2005 && !isFence[nx][ny]) {
isFence[nx][ny]=true;
q.push(Loc(nx, ny));
}
}
}
}
}
cout << ret;
// ENTER CODE ABOVE
}
int main()
{
solve();
}
Also, the reason I have all my code in the solve() function was because this is an assignment and I have to do it this way.
Sidenote: I wrote this code very quickly, so it's very badly formatted.

Schedule round robin matches

How to implement a round robin schedule for an array of 4 elements [1,2,3,4]? The result of the algorithm should be able to display, for each element, the list of the players it will face in chronological order:
(1: 4,2,3)
(2: 3,1,4)
(3: 2,4,1)
(4: 1,3,2)
Line 1: 4,2,3 means that the player (1) will face in order the players (4), (2) and (3).
Of the same way, line 2: 3,1,4 indicates that the player (2) will face in order the players (3), (1) and (2).
We have implemented this code but we encounter a bug when we start filling in the name of the player. Do you have any idea about this problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX_LENGTH 20
#define NUM_MIN_PLAYERS 2
#define NUM_MAX_PLAYERS 20
enum Style
{
STYLE_COMPACT,
STYLE_TABLE
};
enum Format
{
FORMAT_ID,
FORMAT_NAME
};
struct PlayerList
{
unsigned int num_players;
char name[NUM_MAX_PLAYERS][NAME_MAX_LENGTH + 1];
};
struct Grid
{
unsigned int num_players;
unsigned int day[NUM_MAX_PLAYERS]
[NUM_MAX_PLAYERS];
};
void printList(struct PlayerList *list)
{
for (int i = 0; i < list->num_players; i++)
{
printf("%d:%s\n", i + 1, list->name[i]);
}
}
struct Grid calculer_berger(struct PlayerList *list)
{
struct Grid grid;
// algo pour remplir la grid
grid.num_players = list->num_players;
int i, j;
for (i = 0; i < list->num_players - 1; i++)
{
for (j = 0; j < list->num_players - 1; j++)
{
if (i == j)
{
/* edge cases */
grid.day[i][list->num_players - 1] = ((i + j) + (i + j) / list->num_players) % list->num_players;
grid.day[list->num_players - 1][j] = ((i + j) + (i + j) / list->num_players) % list->num_players;
grid.day[i][j] = 0;
}
else
{
grid.day[i][j] = ((i + j) + (i + j) / list->num_players) % list->num_players;
}
}
}
grid.day[0][list->num_players - 1] = list->num_players - 1;
grid.day[list->num_players - 1][list->num_players - 1] = 0;
grid.day[list->num_players - 1][0] = list->num_players - 1;
return grid;
}
void permuter(struct Grid *grid)
{
int tmp;
for (int i = 0; i < grid->num_players; i++)
{
for (int j = 1; j <= grid->num_players / 2; j++)
{
tmp = grid->day[i][j];
grid->day[i][j] = grid->day[i][grid->num_players - j];
grid->day[i][grid->num_players - j] = tmp;
}
}
}
void print_grid(struct Grid *grid, struct PlayerList *list)
{
for (int i = 0; i < grid->num_players; i++)
{
for (int j = 0; j < grid->num_players; j++)
{
if (j == 0)
{
printf("%d:", grid->day[i][j] + 1);
}
else
{
printf("%d", grid->day[i][j] + 1);
if (j < grid->num_players - 1)
{
printf(",");
}
}
}
printf("\n");
}
}
int main(int argc, char **argv)
{
struct PlayerList playerList;
char nom[NAME_MAX_LENGTH + 1];
int nbCharLu = 0;
while ((nbCharLu = fscanf(stdin, "%s", nom)) != -1)
{
strcpy(playerList.name[playerList.num_players], nom);
playerList.num_players++;
}
struct Grid myGrid = calculer_berger(&playerList);
printList(&playerList);
print_grid(&myGrid, &playerList);
printf("Apres la permut\n");
permuter(&myGrid);
print_grid(&myGrid, &playerList);
return 0;
}
Assuming you are storing the elements in an Integer array and that you would like to just display the results.
Here is one implementation....The code should accommodate "N" values because of the use of "sizeof"....
feel free to customize it further....
#include <stdio.h>
int main() {
int i,j;
int array[] = {1,2,3,4};
for(i = 0; i < sizeof(array)/sizeof(int);++i){
printf("(%d :",array[i]);
for(j = 0; j < sizeof(array)/sizeof(int);++j){
if(j == i)
continue;
printf("%d ",array[j]);
}
printf(")\n");
}
}
#include <stdio.h>
void main() {
int mid;
int num;
int j, temp;
int k = 0;
int num1;
int data[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
num = sizeof(data)/sizeof(int);
mid = (sizeof(data)/sizeof(int))/2;
while(k < num - 1){
printf("Round %d ( ",k+1);
num1 = num;
for(int i = 0;i < mid;i++,num1--) /*pairing the competitors in each round*/
printf("%d:%d ",data[i],data[num1-1]);
for(int i = 0,j = num-1; i < num -2;i++,j--){ /* fixing the first competitor and rotating the others clockwise*/
temp = data[j];
data[j] = data[j-1];
data[j-1] = temp;
}
printf(")\n");
k++;
}
}

MPI_Scatterv submatrix with MPI_Type_struct

I'm currently working on a MPI-program and I'm trying to send blocks of a matrix with scatterv to all processes.
Process description
The matrix is given as an array.
First I produce a datatype with MPI_Type_vector to create the necessary block out of the original array.
Second I create a MPI_Type_struct that should hold rows of blocks.
#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#define n 16
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
MPI_Comm comm = MPI_COMM_WORLD;
int p,r;
MPI_Comm_size(comm, &p);
MPI_Comm_rank(comm, &r);
int *arr;
arr = NULL;
if (r == 0){
arr = (int *) malloc(n * n * sizeof(int));
for (int i = 0; i < n * n; i++) arr[i] = i;
for (int i = 0; i < n; i++){
printf("\n");
for (int j = 0; j < n; j++)
printf("%4d", arr[i * n + j]);
}
}
printf("\n");
int ps = sqrt(p);
int ns = n / ps;
if (r == 0) {
printf("ps: %d ns: %d\n", ps, ns);
}
/* create datatype */
MPI_Datatype block;
MPI_Type_vector(ns, ns, n, MPI_INT, &block);
int blocks[ps];
MPI_Aint displs[ps];
for (int i = 0; i < ps; i++) {
blocks[i] = 1;
displs[i] = i * sizeof(int);
}
MPI_Datatype types[ps];
//for (int i = 0; i < ps - 1; i++) types[i] = block;
//types[ps - 1] = MPI_UB;
types[0] = block;
for (int i = 1; i < ps; i++) types[i] = MPI_UB;
//types[0] = block;
//types[1] = MPI_UB;
if (r == 0) {
printf("displs:\n");
for(int i = 0; i < ps; i++) printf("%3ld", displs[i]);
printf("\n");
}
MPI_Datatype row;
MPI_Type_struct(ps, blocks, displs, types, &row);
MPI_Type_commit(&row);
/* prepare scatter */
int sdispl[p]; int sendcounts[p];
for (int i = 0; i < p; i++) {
sdispl[i] = (i % ps) + (i / ps) * (ns * ps);
sendcounts[i] = 1;
}
if (r == 0) {
printf("sdispl: \n");
for (int i = 0; i < 4; i++) printf("%3d", sdispl[i]);
printf("\n");
}
int rcv[ns * ns];
MPI_Scatterv(arr, sendcounts, sdispl, row, rcv, ns * ns, MPI_INT, 0, comm);
int result = 1;
if (r == result) {
printf("result for %d:\n", result);
for (int i = 0; i < ns * ns; i++) {
printf("%4d", rcv[i]);
if ((i+1) % ns == 0) printf("\n");
}
}
if (arr != NULL) free(arr);
MPI_Finalize();
return 0;
}
So far the structure of the blocks is correct.
The problem
The block, that was sent to process r = 1 starts with 3 instead of 4. The block for process r = 2 also starts with 6 and the one for process r = 3 starts with 9.
For r == 4 it jumps to 48.
What it should do
r start
0 0
1 4
2 8
3 12
4 64
5 68
6 ...
15 204
The help I would need
I think, that I'm making some mistake with displ and sdispl.
Compiling and Running the example
The code is compiled with the folowing command:
mpicc -o main main.c -lm
I run the code with:
mpirun -np 16 ./main
Thanks for any help in advance!
With the hint of Zulan I was able to solve my problem.
The following code is based on the excellent answer to subarrays.
#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#define n 8
void print_arr(int *arr, int x) {
printf("\n");
for (int i = 0; i < x*x; i++){
if (i % x == 0) printf("\n");
printf("%4d", arr[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
MPI_Comm comm = MPI_COMM_WORLD;
int p, r;
MPI_Comm_size(comm, &p);
MPI_Comm_rank(comm, &r);
/* number of proceses in dim x and dim y */
int ps = sqrt(p);
/* number of elements in dim x and dim y in sarr */
int ns = n/ps;
/* array of data - distributed by process 0 */
int *arr = NULL;
if (r==0) {
arr = (int *) malloc(n * n * sizeof(int));
for (int i = 0; i < n*n; i++) arr[i] = i;
print_arr(arr, n);
}
MPI_Datatype type, resizedtype;
int sizes[2] = {n,n};
int subsizes[2] = {ns,ns};
int starts[2] = {0,0};
MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_INT, &type);
MPI_Type_create_resized(type, 0, ns*sizeof(int), &resizedtype);
MPI_Type_commit(&resizedtype);
int counts[p];
for (int i = 0; i < p; i++) counts[i] = 1;
int displs[p];
for (int i = 0; i < p; i++) displs[i] = i%ps + i/ps * ns * ps;
/* subarray to store distributed data */
int sarr[ns * ns];
/* send submatrices to all processes */
MPI_Scatterv(arr, counts, displs, resizedtype, sarr, ns*ns, MPI_INT, 0, comm);
/* print received data for process pr */
int pr = 3;
if (r == pr)
print_arr(sarr, ns);
/* free arr */
if (arr != NULL) free(arr);
MPI_Finalize();
return 0;
}
You can compile the example with
mpicc -o main main.c
and run it with
mpirun -np 4 ./main

How to improve Dijkstra algorithm when querying n times?

I'm currently working on a problem at Codechef. You can find the problem statement here:
Delivery Boy
In short, the problem is asking to query n times the shortest path from a start to an end. My solution is to use Dijsktra with priority_queue plus caching the result into a hash_map in case we already had a start. Unfortunately, I got time limit exceed many times and I couldn't find a better way to make it faster. I wonder am I in the right track? or there is a better algorithm to this problem?
By the way, since the contest is still going, please don't post any solution. A hint is more than enough to me. Thanks.
Here is my attempt:
#ifdef __GNUC__
#include <ext/hash_map>
#else
#include <hash_map>
#endif
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <deque>
#include <queue>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
using namespace std;
#ifdef __GNUC__
namespace std {
using namespace __gnu_cxx;
}
#endif
const int MAX_VERTICES = 250;
const int INFINIY = (1 << 28);
int weight[MAX_VERTICES + 1][MAX_VERTICES + 1];
bool visited_start[MAX_VERTICES + 1] = { 0 };
struct vertex {
int node;
int cost;
vertex(int node = 0, int cost = 0)
: node(node), cost(cost) {
}
bool operator <(const vertex& rhs) const {
return cost < rhs.cost;
}
bool operator >(const vertex& rhs) const {
return cost > rhs.cost;
}
};
hash_map<int, vector<vertex> > cache;
typedef priority_queue<vertex, vector<vertex>, greater<vertex> > min_pq;
vector<vertex> dijkstra_compute_path(int start, int n) {
min_pq pq;
vector<vertex> path;
vector<int> visited(n, 0);
int min_cost = 0;
int better_cost;
vertex u;
for (int i = 0; i < n; ++i) {
path.push_back(vertex(i, INFINIY));
}
path[start].cost = 0;
pq.push(vertex(start, path[start].cost));
while (!pq.empty()) {
// extract min cost
u = pq.top();
pq.pop();
// mark it as visited
visited[u.node] = 1;
// for each vertex v that is adjacent to u
for (int v = 0; v < n; ++v) {
// if it's not visited, visit it
if (visited[v] == 0) {
better_cost = path[u.node].cost + weight[u.node][v];
// update cost
if (path[v].cost > better_cost) {
path[v].cost = better_cost;
pq.push(vertex(v, path[v].cost));
}
}
}
}
return path;
}
void check_in_cache(vector<vertex>& path, int start, int no_street) {
if (visited_start[start] == 0) {
path = dijkstra_compute_path(start, no_street);
cache.insert(make_pair(start, path));
visited_start[start] = 1;
}
else {
path = cache[start];
}
}
void display_cost(int stop_at_gas_cost, int direct_cost) {
printf("%d ", stop_at_gas_cost);
if (stop_at_gas_cost > direct_cost) {
printf("%d\n", stop_at_gas_cost - direct_cost);
}
else {
printf("0\n");
}
}
void handle_case_one() {
int no_scenario;
int dummy;
int s, g, d;
scanf("%d", &dummy);
scanf("%d", &no_scenario);
for (int i = 0; i < no_scenario; ++i) {
scanf("%d %d %d", &s, &g, &d);
printf("0 0\n");
}
}
void inout_delivery_boy() {
int no_street;
int no_scenario;
int restaurant;
int gas_station;
int destination;
int stop_at_gas_cost;
int direct_cost;
vector<vertex> direct;
vector<vertex> indirect;
vector<vertex> d;
int c;
scanf("%d", &no_street);
if (no_street == 1) {
handle_case_one();
return;
}
for (int x = 0; x < no_street; ++x) {
for (int y = 0; y < no_street; ++y) {
scanf("%d", &c);
weight[x][y] = c;
}
}
for (int i = 0; i < no_street; ++i) {
d.push_back(vertex(i, INFINIY));
}
scanf("%d", &no_scenario);
for (int i = 0; i < no_scenario; ++i) {
scanf("%d %d %d", &restaurant, &gas_station, &destination);
// check in cache
check_in_cache(direct, restaurant, no_street);
check_in_cache(indirect, gas_station, no_street);
// calculate the cost
stop_at_gas_cost = direct[gas_station].cost + indirect[destination].cost;
direct_cost = direct[destination].cost;
// output
display_cost(stop_at_gas_cost, direct_cost);
}
}
void dijkstra_test(istream& in) {
int start;
int no_street;
int temp[4] = { 0 };
vector<vertex> path;
in >> no_street;
for (int x = 0; x < no_street; ++x) {
for (int y = 0; y < no_street; ++y) {
in >> weight[x][y];
}
}
// arrange
start = 0;
temp[0] = 0;
temp[1] = 2;
temp[2] = 1;
temp[3] = 3;
// act
path = dijkstra_compute_path(start, no_street);
// assert
for (int i = 0; i < no_street; ++i) {
assert(path[i].cost == temp[i]);
}
// arrange
start = 1;
temp[0] = 1;
temp[1] = 0;
temp[2] = 2;
temp[3] = 4;
// act
path = dijkstra_compute_path(start, no_street);
// assert
for (int i = 0; i < no_street; ++i) {
assert(path[i].cost == temp[i]);
}
// arrange
start = 2;
temp[0] = 2;
temp[1] = 1;
temp[2] = 0;
temp[3] = 3;
// act
path = dijkstra_compute_path(start, no_street);
// assert
for (int i = 0; i < no_street; ++i) {
assert(path[i].cost == temp[i]);
}
// arrange
start = 3;
temp[0] = 1;
temp[1] = 1;
temp[2] = 1;
temp[3] = 0;
// act
path = dijkstra_compute_path(start, no_street);
// assert
for (int i = 0; i < no_street; ++i) {
assert(path[i].cost == temp[i]);
}
}
int main() {
// ifstream inf("test_data.txt");
// dijkstra_test(inf);
inout_delivery_boy();
return 0;
}
please notice N is small in the problem. have you tried Floyd shortest path algorithm to pre-calculate shortest path between each two nodes ? it will cost O(N^3) time, which is 250^3=15625000 in the problem, should be easy to be finished running in 1 second. Then you can answer each query in O(1).
the introduction of Floyd :
http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
ps: i think cached dijstra costs a maximum running time of O(N^3) for overall test case as well . but the way you implement the cache will spend more unnecessary time on memory copying, which may lead to a TLE. Just a guess.
Indeed Floyd-Warshall's Algorithm is better than Dijkstra's in this case, the complexity for Dijkstra is O(m*n^2) and in this problem M is much much higher than N so the O(n^3) time complexity of Floyd-Warshall is better.

The most efficient way to remove all characters in the 1st string from the 2nd string?

I was asked about this question. I can only think of a O(nm) algorithm if n is the length of the 1st string and m is the length of the 2nd string.
Well, you can do it in O(n + m). Just create a reference table showing whether character exists in first string. Something like this (pseudo-code in no particular language)
// fill the table
for (int i = 0; i < a.length; ++i) {
characterExists[a[i]] = true;
}
// iterate over second string
for (int i = 0; i < b.length; ++i) {
if !characterExists[b[i]] {
// remove char (or do whatever else you want)
}
}
Have you checked out the Boyer-Moore String Search Algorithm?
The worst-case to find all occurrences
in a text needs approximately 3*N
comparisons, hence the complexity is
O(n), regardless whether the text
contains a match or not. This
proof took some years to determine. In
the year the algorithm was devised,
1977, the maximum number of
comparisons was shown to be no more
than 6*N; in 1980 it was shown to be
no more than 4*N, until Cole's result
in Sep 1991.
C implementation:
#include <limits.h>
#include <string.h>
#define ALPHABET_SIZE (1 << CHAR_BIT)
static void compute_prefix(const char* str, size_t size, int result[size]) {
size_t q;
int k;
result[0] = 0;
k = 0;
for (q = 1; q < size; q++) {
while (k > 0 && str[k] != str[q])
k = result[k-1];
if (str[k] == str[q])
k++;
result[q] = k;
}
}
static void prepare_badcharacter_heuristic(const char *str, size_t size,
int result[ALPHABET_SIZE]) {
size_t i;
for (i = 0; i < ALPHABET_SIZE; i++)
result[i] = -1;
for (i = 0; i < size; i++)
result[(size_t) str[i]] = i;
}
void prepare_goodsuffix_heuristic(const char *normal, size_t size,
int result[size + 1]) {
char *left = (char *) normal;
char *right = left + size;
char reversed[size+1];
char *tmp = reversed + size;
size_t i;
/* reverse string */
*tmp = 0;
while (left < right)
*(--tmp) = *(left++);
int prefix_normal[size];
int prefix_reversed[size];
compute_prefix(normal, size, prefix_normal);
compute_prefix(reversed, size, prefix_reversed);
for (i = 0; i <= size; i++) {
result[i] = size - prefix_normal[size-1];
}
for (i = 0; i < size; i++) {
const int j = size - prefix_reversed[i];
const int k = i - prefix_reversed[i]+1;
if (result[j] > k)
result[j] = k;
}
}
/*
* Boyer-Moore search algorithm
*/
const char *boyermoore_search(const char *haystack, const char *needle) {
/*
* Calc string sizes
*/
size_t needle_len, haystack_len;
needle_len = strlen(needle);
haystack_len = strlen(haystack);
/*
* Simple checks
*/
if(haystack_len == 0)
return NULL;
if(needle_len == 0)
return haystack;
/*
* Initialize heuristics
*/
int badcharacter[ALPHABET_SIZE];
int goodsuffix[needle_len+1];
prepare_badcharacter_heuristic(needle, needle_len, badcharacter);
prepare_goodsuffix_heuristic(needle, needle_len, goodsuffix);
/*
* Boyer-Moore search
*/
size_t s = 0;
while(s <= (haystack_len - needle_len))
{
size_t j = needle_len;
while(j > 0 && needle[j-1] == haystack[s+j-1])
j--;
if(j > 0)
{
int k = badcharacter[(size_t) haystack[s+j-1]];
int m;
if(k < (int)j && (m = j-k-1) > goodsuffix[j])
s+= m;
else
s+= goodsuffix[j];
}
else
{
return haystack + s;
}
}
/* not found */
return NULL;
}

Resources