I need to find the closest name in a list - c

I had a really big file in this format that I passed into a string.
International Workshop on Collaborative Virtual Environments B3
International 3D System Integration Conference B1
Three-Dimensional Image Processing, Measurement and Applications B3
Eurographics Workshop on 3D Object Retrieval B2
...
And I have a name that matches one of those lines in the file.
I need a function that loops through this longer string, finds the line with the most similarity (I'm using levershtein string distance function to measure the distance) and returns me the rating, which is the letter and number at the end of the line.
// Return the min number between three integers
int min(int a, int b, int c) {
int res;
if(a <= b && a <= c)
res = a;
else if(b <= a && b <= c)
res = b;
else if(c <= a && c <= b)
res = c;
return res;
}
// Returns a int that means the distance between two strings
int levenshtein(char *s1, char *s2) {
unsigned int x, y, s1len, s2len = 0;
s1len = strlen(s1);
s2len = strlen(s2);
unsigned int matrix[s2len+1][s1len+1];
matrix[0][0] = 0;
for (x = 1; x <= s2len; x++)
matrix[x][0] = matrix[x-1][0] + 1;
for (y = 1; y <= s1len; y++)
matrix[0][y] = matrix[0][y-1] + 1;
for (x = 1; x <= s2len; x++)
for (y = 1; y <= s1len; y++)
matrix[x][y] = min(matrix[x-1][y] + 1, matrix[x][y-1] + 1, matrix[x-1][y-1] + (s1[y-1] == s2[x-1] ? 0 : 1));
return(matrix[s2len][s1len]);
}
For example:
if i have the name: International Workshop on Collaborativa Virtual Environments Sao Paulo, i want the function to return B3. Sao Paulo being the reason why i need the string distance function.
I don't really know how to loop through the string to compare.

Related

couldn't find out how to solve this algorithm problem

I am beginner I tried so many times but I couldn't solve this problem I will be very pleased if you help me...
the question is:
Let x be an integer, and R(x) is a function that returns the reverse of the x in terms of its digits.
For example , if x:1234 then R(x)=4321.
Let’s call a positive integer mirror-friendly if it satisfies the following condition: π‘₯ + 𝑅(π‘₯) = 𝑦^2 π‘€β„Žπ‘’π‘Ÿπ‘’ 𝑦 𝑖𝑠 π‘Žπ‘› π‘–π‘›π‘‘π‘’π‘”π‘’π‘Ÿ
Write a program that reads a positive integer as n from the user and prints out a line for each of the first n mirror-friendly integers as follows: x + R(x) = y^2
Example: If the user enters 5 as n, then the program should print out the following:
2 + 2 = 2^2
8 + 8 = 4^2
29 + 92 = 11^2
38 + 83 = 11^2
47 + 74 = 11^2
Here is the my code:
int
reverse(int num)
{
int reverse,
f,
i;
reverse = 0;
i = 0;
for (; i < num + i; i++) {
f = num % 10;
reverse = (reverse * 10) + f;
num /= 10;
}
return reverse;
}
int
sqrt(int n)
{
int i = 1;
int sqrt;
for (; i <= n; i++) {
sqrt = i * i;
}
return sqrt;
}
int
main()
{
int j = 1;
int main_num = 0;
for (; main_num <= 0;) {
printf("Please enter a positive integer: \n");
scanf_s("%d", &main_num);
}
int count = 0;
for (int i = 1; i <= main_num; i++) {
for (; j <= main_num; j++) {
if (j + reverse(j) == sqrt(?)) {
printf("%d + %d = %d\n", j, reverse(j), sqrt(?));
}
}
}
}
A few issues ...
sqrt does not compute the square root
reverse seems overly complicated
main_num (i.e. n from the problem statement) is the desired maximum count of matches and not the limit on x
Too many repeated calls to sqrt and reverse
No argument given to sqrt
The if in main to detect a match is incorrect.
sqrt conflicts with a standard function.
The variables you're using don't match the names used in the problem statement.
The printf didn't follow the expected output format.
Using a function scoped variable that is the same as the function is a bit confusing (to humans and the compiler).
Unfortunately, I've had to heavily refactor the code. I've changed all the variable names to match the names used in the problem statement for clarity:
#include <stdio.h>
#include <stdlib.h>
#ifdef DEBUG
#define dbgprt(_fmt...) printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
int
reverse(int x)
{
int r = 0;
for (; x != 0; x /= 10) {
int f = x % 10;
r = (r * 10) + f;
}
return r;
}
int
isqrt(int x)
{
int y = 1;
while (1) {
int y2 = y * y;
if (y2 >= x)
break;
++y;
}
return y;
}
int
main(int argc,char **argv)
{
int n = -1;
--argc;
++argv;
if (argc > 0) {
n = atoi(*argv);
printf("Positive integer is %d\n",n);
}
while (n <= 0) {
printf("Please enter a positive integer:\n");
scanf("%d", &n);
}
int x = 1234;
dbgprt("x=%d r=%d\n",x,reverse(x));
int count = 0;
for (x = 1; count < n; ++x) {
dbgprt("\nx=%d count=%d\n",x,count);
// get reverse of number (i.e. R(x))
int r = reverse(x);
dbgprt("r=%d\n",r);
// get x + R(x)
int xr = x + r;
dbgprt("xr=%d\n",xr);
// get y
int y = isqrt(xr);
dbgprt("y=%d\n",y);
if (xr == (y * y)) {
printf("%d + %d = %d^2\n", x, r, y);
++count;
}
}
return 0;
}
Here is the program output:
Positive integer is 5
2 + 2 = 2^2
8 + 8 = 4^2
29 + 92 = 11^2
38 + 83 = 11^2
47 + 74 = 11^2
UPDATE:
The above isqrt uses a linear search. So, it's a bit slow.
Here is a version that uses a binary search:
// isqrt -- get sqrt (binary search)
int
isqrt(int x)
{
int ylo = 1;
int yhi = x;
int ymid = 0;
// binary search
while (ylo <= yhi) {
ymid = (ylo + yhi) / 2;
int y2 = ymid * ymid;
// exact match (i.e. x == y^2)
if (y2 == x)
break;
if (y2 > x)
yhi = ymid - 1;
else
ylo = ymid + 1;
}
return ymid;
}
UPDATE #2:
The above code doesn't scale too well for very large x values (i.e. large n values).
So, main should check for wraparound to a negative number for x.
And, a possibly safer equation for isqrt is:
ymid = ylo + ((yhi - ylo) / 2);
Here is an updated version:
#include <stdio.h>
#include <stdlib.h>
#ifdef DEBUG
#define dbgprt(_fmt...) printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
// reverse -- reverse a number (e.g. 1234 --> 4321)
int
reverse(int x)
{
int r = 0;
for (; x != 0; x /= 10) {
int f = x % 10;
r = (r * 10) + f;
}
return r;
}
// isqrt -- get sqrt (linear search)
int
isqrt(int x)
{
int y = 1;
while (1) {
int y2 = y * y;
if (y2 >= x)
break;
++y;
}
return y;
}
// isqrt2 -- get sqrt (binary search)
int
isqrt2(int x)
{
int ylo = 1;
int yhi = x;
int ymid = 0;
// binary search
while (ylo <= yhi) {
#if 0
ymid = (ylo + yhi) / 2;
#else
ymid = ylo + ((yhi - ylo) / 2);
#endif
int y2 = ymid * ymid;
// exact match (i.e. x == y^2)
if (y2 == x)
break;
if (y2 > x)
yhi = ymid - 1;
else
ylo = ymid + 1;
}
return ymid;
}
int
main(int argc,char **argv)
{
int n = -1;
--argc;
++argv;
setlinebuf(stdout);
// take number from command line
if (argc > 0) {
n = atoi(*argv);
printf("Positive integer is %d\n",n);
}
// prompt user for expected/maximum count
while (n <= 0) {
printf("Please enter a positive integer:\n");
scanf("%d", &n);
}
int x = 1234;
dbgprt("x=%d r=%d\n",x,reverse(x));
int count = 0;
for (x = 1; (x > 0) && (count < n); ++x) {
dbgprt("\nx=%d count=%d\n",x,count);
// get reverse of number (i.e. R(x))
int r = reverse(x);
dbgprt("r=%d\n",r);
// get x + R(x)
int xr = x + r;
dbgprt("xr=%d\n",xr);
// get y
#ifdef ISQRTSLOW
int y = isqrt(xr);
#else
int y = isqrt2(xr);
#endif
dbgprt("y=%d\n",y);
if (xr == (y * y)) {
printf("%d + %d = %d^2\n", x, r, y);
++count;
}
}
return 0;
}
In the above code, I've used cpp conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Note: this can be cleaned up by running the file through unifdef -k
for(;i<num+i;i++)
is equal to
for(; 0<num;i++)
or for(; num;i++) if we are working with positive values only.
or even to while(num)
So, we don't need variable i in reverse function.
We don't need cycle at all in sqrt function. Just return n * n; is ok. But it is not sqrt then
The last cycle is too strange. At least variable j is not initialized.

Comparing two triangles in C (3, 3, 4 and 4, 3, 3 for example)

I need to find all possible triangles in a set of integers. I successfully got the result, but I have many duplicates, for example:
A(3, 3, 4) == B(4, 3, 3)
I don't need to find similar triangles, I need to know when they are equal.
I tried to save my triangles as structs and wanted to compare them:
struct triangle
{
int a;
int b; // I stored all found triangles this way
int c;
};
int getNumberOfDuplicates(struct triangle savedTriangles[], int size) {
int count = 0;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
int a,b,c,x,y,z;
if (i != j) {
a = savedTriangles[i].a; b = savedTriangles[i].b; c = savedTriangles[i].c;
x = savedTriangles[j].a; y = savedTriangles[j].b; z = savedTriangles[j].c;
if (areTheSame) { // Here I don't know how to compare them
count++;
}
}
}
}
return count;
Is there any mathematical way to compare them? Or any programming way?
The simplest solution would be to sort the three numbers.
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
void bubble_sort(int *a, int *b, int *c) {
if (a > b) swap(&a, &b);
if (b > c) swap(&b, &c);
if (a > b) swap(&a, &b);
}
At which point it should be trivial to compare if they are equal.
You have to do two modifications to your code:
Just compare a triangle to the followers only, you are now counting it twice, which will give you double the desired result.
Sort the lengths in ascending order by using min and max, then compare them.
So your code should look like this:
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) { //Start from i + 1 not 0
int a, b, c, x, y, z, a1, b1, c1, x1, y1, z1;
a = savedTriangles[i].a; b = savedTriangles[i].b; c = savedTriangles[i].c;
x = savedTriangles[j].a; y = savedTriangles[j].b; z = savedTriangles[j].c;
a1 = min(a, min(b, c));
c1 = max(a, max(b, c));
b1 = a + b + c - a1 - c1;
x1 = min(x, min(y, z));
z1 = max(x, max(y, z));
y1 = x + y + z - x1 - z1;
if (a1 == x1 && b1 == y1 && c1 == z1)
count++;
}
}
int min (int a, int b)
{
return a < b ? a : b;
}
int max (int a, int b)
{
return a > b ? a : b;
}
There is a mathematical way by getting their sum, product and sum of their squares without the need to sort them, any triplet will give a unique set of results regardless of their order according to this, so the alternative code should look like this:
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
int a, b, c, x, y, z, s1, s2, ss1, ss2, p1, p2;
a = savedTriangles[i].a; b = savedTriangles[i].b; c = savedTriangles[i].c;
x = savedTriangles[j].a; y = savedTriangles[j].b; z = savedTriangles[j].c;
s1 = a + b + c;
ss1 = a * a + b * b + c * c;
p1 = a * b * c;
s2 = x + y + c;
ss2 = x * x + y * y + z * z;
p2 = x * y * z;
if (s1 == s2 && ss1 == ss2 && p1 == p2)
count++;
}
}
Assuming the list is complete, every triangle will be repeated for every permutation of its sides a, b, c. Therefore each triangle is a duplicate of one with a <= b <= c, so it is enough to only check those, and automatically count any triangle with b < a or c < b as a duplicate.
int getNumberOfDuplicates(struct triangle savedTriangles[], int size){
int count = 0;
for (int i = 0; i < size; i++){
int a = savedTriangles[i].a,
b = savedTriangles[i].b,
c = savedTriangles[i].c;
if(b < a || c < b){
count++;
continue;
}
for (int j = i + 1; j < size; j++){
int x = savedTriangles[j].a,
y = savedTriangles[j].b,
z = savedTriangles[j].c;
if(a == x && b == y && c == z){
count++;
break;
}
}
}
return count;
}

Resizing an image stored as a 'strided' array: can I make this bilinear interpolation faster?

I have a piece of C code that is part of a public repository (Darknet) which is supposed to resize an image using bilinear interpolation. Because of the way the rest of the code deals with images, the image is stored as a one-dimensional array where the pixel values from the original 3 channel image are read in strides. The value corresponding to pixel (x, y, k) (x: column, y: row, k: channel) is thus stored in the location x + w.h + w.h.c in the 1D array.
The resize function that is actually part of Darknet is taking a considerable amount of time in the pre-processing stage, possibly because of its nested for loops that iterate over the rows and columns and attempt to access corresponding values, as well as possibly the type conversions: hence I am trying to create a more optimized version of it. The original code for resizing is as follows. im is the original image, thus im.w and im.h are the original width and height. w and h are the target width and height.
image resize_image(image im, int w, int h)
{
image resized = make_image(w, h, im.c);
image part = make_image(w, im.h, im.c);
int r, c, k;
float w_scale = (float)(im.w - 1) / (w - 1);
float h_scale = (float)(im.h - 1) / (h - 1);
for(k = 0; k < im.c; ++k){
for(r = 0; r < im.h; ++r){
for(c = 0; c < w; ++c){
float val = 0;
if(c == w-1 || im.w == 1){
val = get_pixel(im, im.w-1, r, k);
} else {
float sx = c*w_scale;
int ix = (int) sx;
float dx = sx - ix;
val = (1 - dx) * get_pixel(im, ix, r, k) + dx * get_pixel(im, ix+1, r, k);
}
set_pixel(part, c, r, k, val);
}
}
}
for(k = 0; k < im.c; ++k){
for(r = 0; r < h; ++r){
float sy = r*h_scale;
int iy = (int) sy;
float dy = sy - iy;
for(c = 0; c < w; ++c){
float val = (1-dy) * get_pixel(part, c, iy, k);
set_pixel(resized, c, r, k, val);
}
if(r == h-1 || im.h == 1) continue;
for(c = 0; c < w; ++c){
float val = dy * get_pixel(part, c, iy+1, k);
add_pixel(resized, c, r, k, val);
}
}
}
free_image(part);
return resized;
}
Is there a way to make this function faster: for instance, by creating a more optimized way to access the pixels instead of this strided read? Also, I note here that in my case:
The dimensions of the source and resized images will be fixed, so my 'custom' resize function does not have to be size-independent. I am going from 640x360 to the dimensions 626x352.
The target platform is an NVIDIA Jetson with an ARM CPU, so instructions like AVX2 are not applicable in my case. But I do have access to CUDA.
I have to make a note here that because of the requirements of my project, this resize function is actually part of a library (.so) that's being called from Python. So I cannot keep anything "in memory" per se, such as CUDA texture objects etc., so creating them again and again might actually create more overhead on the CUDA side.
Any suggestions in improving this routine would be very helpful.
[As Stargateur mentioned] get_pixel et. al are wasteful. Most pixel accesses can be handled with a pointer. This is a pretty standard thing to do when processing an image where speed is required.
Most accesses creep along the x dimension, so we can just increment pointers.
From get_pixel, create this function:
static float *loc_pixel(image m, int x, int y, int c)
{
return &m.data[(c * m.h * m.w) + (y * m.w) + x];
}
The if in resize_image can be moved out of the first inner for loop by some restructuring.
In all for loops, we can remove all *_pixel functions from the inner loop by using loc_pixel and pointers.
Here's a refactored version that uses only pointers that should be faster. Note that I've coded this but neither tested nor compiled it. I think it's pretty close, but you should double check to be sure.
One thing you could add that I didn't do is have loc_pixel take a pointer to the image (i.e. image *m) instead of passing the entire struct.
Also, you could experiment with replacing src[0] with src[c] and *dst with dst[c]. This would eliminate some ++src and ++dst and might be faster. It might also allow the compiler to understand the loops better so it could use any arm vector instructions and might make it more amenable to CUDA. YMMV.
image
resize_image(image im, int w, int h)
{
image resized = make_image(w, h, im.c);
image part = make_image(w, im.h, im.c);
int r,
c,
k;
float w_scale = (float) (im.w - 1) / (w - 1);
float h_scale = (float) (im.h - 1) / (h - 1);
int wm1 = w - 1;
float val;
float marg;
float *src;
float *dst;
for (k = 0; k < im.c; ++k) {
for (r = 0; r < im.h; ++r) {
src = loc_pixel(im, 0, r, k);
dst = loc_pixel(part, 0, r, k);
marg = get_pixel(im, im.w - 1, r, k);
if (im.w == 1) {
for (c = 0; c < w; ++c, ++dst)
*dst = marg;
continue;
}
for (c = 0; c < wm1; ++c, ++src, ++dst) {
float sx = c * w_scale;
int ix = (int) sx;
float dx = sx - ix;
val = (1 - dx) * src[0] + dx * src[1];
*dst = val;
}
// handle c == w - 1 case
*dst = marg;
}
}
for (k = 0; k < im.c; ++k) {
for (r = 0; r < h; ++r) {
float sy = r * h_scale;
int iy = (int) sy;
float dy = sy - iy;
src = loc_pixel(part, 0, iy, k);
dst = loc_pixel(resized, 0, r, k);
for (c = 0; c < w; ++c, ++src, ++dst) {
val = (1 - dy) * src[0];
*dst = val;
}
if (r == h - 1 || im.h == 1)
continue;
src = loc_pixel(part, 0, iy + 1, k);
dst = loc_pixel(resized, 0, r, k, val);
for (c = 0; c < w; ++c, ++src, ++dst) {
val = dy * src[0];
*dst += val;
}
}
}
free_image(part);
return resized;
}

Convex hull length in C

Im making a program to calculate convex hull length of 2D points.
On the input there is a number of points n and then the coordinates of each point.
for example:
6
-8 -3
-6 1
-5 -2
-3 1
-3 4
2 18
and output is simply the length of the convex hull.
my code looks like this so far:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct point
{
double x;
double y;
}POINT,VECTOR;
POINT b[1000];
VECTOR normal;
int n;
int upper_lower(int i, VECTOR ab, double c) {
double x, y,result;
y = b[i].y;
x = normal.x*b[i].x;
result = -(x + c) / normal.y;
if (y>result) return 1;
if (y == result) return 0;
else
return -1;
}
int ccw(VECTOR v,VECTOR v2)
{
double cp;
cp = v2.x*v.y - v2.y*v.x;
if (cp == abs(cp)) return 1;
else
return -1;
}
double vector_length(VECTOR v)
{
return sqrt(pow(v.x, 2) + pow(v.y, 2));
}
int cmp_points(const void *p1, const void *p2)
{
const POINT *pt1 = p1;
const POINT *pt2 = p2;
// do primary compare on x
if (pt1->x > pt2->x)
return 1;
if (pt1->x < pt2->x)
return -1;
// pt1->x == pt2->x - do secondary compare on y...
if (pt1->y > pt2->y)
return 1;
if (pt1->y < pt2->y)
return -1;
// pt1 == pt2
return 0;
}
int main()
{
int i,poloha,upper[1000],lower[1000],h=0,d=0;
scanf("%d", &n);
if (n <= 0 && n > 1000) return 0;
for (i = 0; i < n; i++)
{
scanf("%lf %lf", &b[i].x, &b[i].y);
}
qsort(b, n, sizeof(POINT), cmp_points);
//split in half
VECTOR ab;
double c;
ab.x = b[n - 1].x - b[0].x;
ab.y = b[n - 1].y - b[0].y;
normal.x = -ab.y;
normal.y = ab.x;
c = -normal.x*b[0].x - (normal.y*b[0].y);
for (i = 0; i < n; i++)
{
poloha = upper_lower(i,ab,c);
if (poloha == 1) upper[h++] = i;
if (poloha == -1) lower[d++]=i;
if (poloha == 0)
{
upper[h++] = i;
lower[d++] = i;
}
}
int j = 0;
double v, length = 0;
VECTOR v1, v2, v3,v4;
v3.x = 0; v3.y = 0;
//lower part
for (i = 0; ; i++)
{
int in = 0;
if (lower[i + 2] < 0)
{
v1.x = b[lower[i + 1]].x - b[lower[0]].x;
v1.y = b[lower[i + 1]].y - b[lower[0]].y;
v2.x = b[lower[i]].x - b[lower[i + 1]].x;
v2.y = b[lower[i]].y - b[lower[i + 1]].y;
lenght += vector_length(v1);
length += vector_length(v2);
break;
}
v1.x = b[lower[i + 1]].x - b[lower[i]].x;
v1.y = b[lower[i + 1]].y - b[lower[i]].y;
v2.x = b[lower[i + 2]].x - b[lower[i]].x;
v2.y = b[lower[i + 2]].y - b[lower[i]].y;
in = ccw(v1, v2);
if (in == 1)
{
length += vector_length(v1);
v3 = v2;
v4 = v1;
}
if (in == -1)
{
length -= vector_length(v4);
if (v3.x != 0 && v3.y != 0)
{
length += vector_length(v3);
v3.x = 0; v3.y = 0;
}
else
{
length += vector_length(v2);
}
}
}
printf("%.3lf", length);
return 0;
}
the problem is that in the last part where I try to compute the length...I just dont know how to finish it..no matter what I try it never works as I want to. Could you guys give me some advice?
I can't see a standard answer, so here's the algorithm:
Choose a point roughly in the centre of your point cloud. Then sort the points radially, by angle from the centre. The topmost point must be in the convex hull, so define it as having an angle of 0.0 and being first in the list.
Now go though. Put point 2 in the "tentative" hull list. Then check point 3. If the angle P1-P2-P3 is concave (relative to the centre point), remove P2 from the list, if it is convex, keep it. Continue like this, backtracking and removing points if they go concave. You only need two points in your "tentative" list, once you have three, they become definite.
You stop when you go full circle and get back to P1.
There are many known convex hull algorithms, one of the simplest of which is the gift wrapping algorithm. Here's an implementation that fits in your program where the points have been input and sorted:
int j = 0; // after sorting, b[0] is leftmost point, must be on an edge
double length = 0;
VECTOR v1, v2, vv;
v1.x = 0, v1.y = 1; // start by measuring angles from vertical
int iv; // index of next edge point
do // find next egde point by minimum angle
{
double lv1 = vector_length(v1), lv2, lv;
double cv = -1; // minimal possible cosine value
for (i = 0; i < n; ++i) if (i != j)
{ // compute cosine of angle between v1 and (b[j]-->b[i]) = v2
v2.x = b[i].x-b[j].x, v2.y = b[i].y-b[j].y;
double c = (v1.x*v2.x + v1.y*v2.y) / lv1 / (lv2 = vector_length(v2));
if (c > cv) cv = c, iv = i, lv = lv2, vv = v2; // new maximum cosine
}
if (v == -1) break;
// printf("%d:%f,%f-->%d:%f,%f = %f\n", j, b[j], iv, b[iv], lv);
length += lv;
v1 = vv; // found edge is new reference edge
} while (j = iv); // repeat while not at start again
printf("%.3lf\n", length);

How to divide digits and compare them, in C

Write a program that will find the largest number smaller than N that is totally different from a given number X. One number is totally different from other only if it doesn't contain any of the digits from the other number. N and X are read from standard input. The problem should be solved without the use of arrays.
Example Input 1: 400 897
Example Output 1: 366
Example Input 2: 1000 1236498
Example Output 2:777
No it's not homework, it was on one of the midterms and it's been killing me. I though about taking the first numbers last digit with %10 then taking the second numbers digit with %10 comparing them but...I just can't get it to work...I ended up with an endless loop...I just don't understand how to get every digit of the numbers and compare them to the other number.
#include <stdio.h>
int main () {
int N, X, num_N, num_X, i, lastDigit_N, lastDigit_X, flag, smaller_than_N;
scanf("%d%d", &N, &X);
smaller_than_N = N - 1;
for (i = smaller_than_N; i > 0; i--) {
num_N = i;
num_X = X;
flag = 0;
while (num_N > 0) {
lastDigit_N = num_N % 10;
while (num_X > 0) {
lastDigit_X = num_X % 10;
if (lastDigit_N == lastDigit_X) {
break;
}
else {
flag = 1;
}
num_X /= 10;
}
num_N /= 10;
}
if(flag) {
printf("%d", i);
break;
}
}
return 0;
}
You could build a bitmask for your numbers showing the digits which are contained.
uint16_t num2bitmask(int number)
{
uint16_t result = 0;
while (number) {
int digit = number % 10;
number /= 10;
result |= (1 << digit);
}
return result;
}
With this function, you can create your bitmask for X and then iterate from N-1 down to 1 until you find a value which doesn't have any bits in common with the other value.
If you have a number with digits d_1, d_2, ..., d_n, and you're allowed to use digits in the set D, then possible solutions look like:
d_1, ..., d_{i-1}, max(d in D | d < d_i), max(d in D), ..., max(d in D).
That is, the digits are the same up to some point, then the next digit is as large as possible while being below the input digit, then the rest are just as large as possible.
Not all these "solutions" will be valid, but if you iterate through them in reverse order (there's exactly n for an input number of size n), the first valid one you find is the answer.
Some code, including tests:
#include <stdio.h>
int digit_length(int a) {
int r = 0;
while (a) {
a /= 10;
r += 1;
}
return r;
}
int get_digit(int a, int k) {
while (k--) a /= 10;
return a % 10;
}
int largest_different(int a, int b) {
int lena = digit_length(a);
int invalid = b ? 0 : 1;
for (; b; b /= 10) invalid |= 1 << (b % 10);
int max_valid = 9;
while (max_valid >= 0 && (invalid & (1 << max_valid)))
max_valid--;
if (max_valid == -1) return -1;
for (int i = 0; i < lena; i++) {
int d = get_digit(a, i) - 1;
while (d >= 0 && (invalid & (1 << d)))d--;
if (d < 0) continue;
int solution = 0;
for (int k = lena - 1; k >= 0; k--) {
solution *= 10;
solution += (k < i ? max_valid : k > i ? get_digit(a, k) : d);
}
return solution;
}
return -1;
}
int main(int argc, char *argv[]) {
struct {int n; int x; int want;} examples[] = {
{400, 897, 366},
{1000, 1236498, 777},
{998, 123, 997},
};
int error = 0;
for (int i = 0; i < sizeof(examples) / sizeof(*examples); i++) {
int got = largest_different(examples[i].n, examples[i].x);
if (got != examples[i].want) {
error = 1;
printf("largest_different(%d, %d) = %d, want %d\n",
examples[i].n, examples[i].x, got, examples[i].want);
}
}
return error;
}
There's not always a solution. In that case, the function returns -1.

Resources