function to find the longest increasing subsequence without arrays - c

I need to make a program in C with those instructions:
the problem is its kinda easy to do with arrays but without them,I cant think anything else.
we need to write a function that takes int n and then takes the sequences of numbers, the function need to return us the sum of the biggest sequence.
for n = 8 and the sequence = 2,4,6,8,11,14,17,9' (there is 2 long sequences of 4, (when 8 starts the new sequence and closes the current sequence) here we will get the print 50.`
for n = 2 and the sequence 7,19 the function will print 26.
for n = 8 and the sequence 8,6,4,2,11,14,15,16
the longest length is 4 so the function will print 20.
can't find any solution here without arrays
printf("please choose a n");
scanf("%d", &n);
y = n;
if (n == 1)
{
printf("Please enter the next number ");
scanf("%d", &series);
return series;
}
else
if (n == 2)
{
while (i < 2) {
{
printf("Please enter the next number ");
scanf("%d", &series);
sum += series;
}
return sum;
}
printf("Plase choose another number");
scanf("%d", &last);
sum += last;
printf("please choose another number");
scanf("%d", &series);
d = series - last;
sum = series + last;
bSum = sum;
for (i = 2; i < n; i++)
{
last = series;
printf("Please write another number; ");
scanf("%d", &series);
if (series - last == d)
{
sum += series;
count++;
}
if (series - last != d)
{
if (count > length)
{
bSum = sum;
length = count;
}
else if (count == length && sum > bSum)
{
bSum = sum;
}
}
}

I had coded this up, but needed clarification from OP (see my top comments).
As a result ...
I added code to pick a sequence of equal length to the best but with a larger sum.
Because it was minimal changes to my code, I chose that the longest sequence wins:
For input of -2 -1 1 2, this is a sequence of 4 with sum 0. It is not two sequences of 2 -2 -1 and 1 2 with sum 3.
For input of 1 1 1 1 1, this is a sequence of 5 with sum 5 and not 5 sequences of 1 [each] with sum 1
Here is the code. It is annotated:
#include <stdio.h>
int
main(void)
{
// get count of sequence numbers
int n;
scanf("%d",&n);
// length of current sequence
int curlen = 0;
// sum of current sequence
int cursum = 0;
// value of current number
int curval;
// value of previous number
int oldval;
// get the first number
scanf("%d",&oldval);
// add it to the current sequence
curlen += 1;
cursum += oldval;
// initialize the best sequence from the current one
int bestsum = cursum;
int bestlen = curlen;
// get all remaining numbers in the sequence
for (int i = 1; i < n; ++i, oldval = curval) {
// get new current number
if (scanf("%d",&curval) != 1) {
fprintf(stderr,"too short\n");
break;
}
// reset the current sequence if we're not increasing
if (curval < oldval) {
cursum = 0;
curlen = 0;
}
// add to the current sequence
cursum += curval;
curlen += 1;
// save off the longest sequence we've seen
if (curlen > bestlen) {
bestlen = curlen;
bestsum = cursum;
continue;
}
// save off a sequence that is the same length as the best but has a
// larger sum
if ((curlen == bestlen) && (cursum > bestsum)) {
bestsum = cursum;
continue;
}
}
// print the final/best sum
printf("%d\n",bestsum);
return 0;
}
Input:
4
-2 -1 1 2
Output: 0
Input:
5
1 1 1 1 1
Output: 5
Input:
2
7 19
Output: 26
Input:
8
2 4 6 8 11 14 17 9
Output: 62
Input:
8
8 6 4 2 11 14 15 16
Output: 58
Input:
12
1 2 3 4
2 3 4 5
3 4 5 6
Output: 18
Input:
2
2 1
Output: 2
Here is the perl script that I used to generate the tests:
Edit: Updated for example below.
#!/usr/bin/perl
# runseq -- run sequence program
#
# options:
# "-D" -- cc -D options
# "-S<sfile>" -- source file (DEFAULT: seq.c)
# "-clip" -- send output to xclip program
# "-d" -- debug runseq script
#
# arguments:
# 1-- [optional] comma separated list of sequence numbers (e.g. 3,7 2,1)
master(#ARGV);
exit(0);
# master -- master control
sub master
{
my(#argv) = #_;
optdcd(\#argv,
"+opt_D","opt_S","opt_clip");
# get source file
$sroot = $opt_S;
$sroot //= "seq";
$sroot =~ s/[.].+$//;
zprtx("compiling %s ...\n",$sroot);
$sfile = "$sroot.c";
sysfault("runseq: no source file\n")
unless (-e $sfile);
push(#cc,"cc");
push(#cc,"-o$sroot");
foreach $opt (#opt_D) {
push(#cc,"-D$opt");
}
push(#cc,$sfile);
$cmd = join(" ",#cc);
zprtx("%s\n",$cmd);
$code = vxsystem(#cc);
exit(1) if ($code);
$tmpfile = "inp.txt";
# send to xclip program
if ($opt_clip) {
open($xfout,"|xclip");
}
else {
$xfout = \*STDOUT;
}
{
# take tests from command line
if (#argv > 0) {
foreach $arg (#argv) {
$arg =~ s/,/ /g;
#body = ($arg);
dosum();
}
last;
}
# get test data from below
$xfdata = \*seq::DATA;
while ($dat = <$xfdata>) {
chomp($dat);
# ignore comments
next if ($dat =~ /^\s*#/);
# blank line separates tests
if ($dat =~ /^\s*$/) {
dosum();
next;
}
push(#body,$dat);
}
}
# do final test
dosum()
if (#body > 0);
close($xfout)
if ($opt_clip);
}
# optdcd -- decode command line options
sub optdcd
{
my(#syms) = #_;
my($argv);
my($arg);
my($ary);
my($symlhs,$symrhs,$val,$match);
$argv = shift(#syms);
# get options
while (#$argv > 0) {
$arg = $argv->[0];
last unless ($arg =~ /^-/);
shift(#$argv);
$match = 0;
foreach $symrhs (#syms) {
$symlhs = $symrhs;
$ary = ($symlhs =~ s/^[+]//);
$opt = $symlhs;
$opt =~ s/^opt_/-/;
zprt("optdcd: TRYARG arg='%s' symrhs='%s' symlhs='%s' opt='%s' ary=%d\n",
$arg,$symrhs,$symlhs,$opt,$ary);
if ($arg =~ /^$opt(.*)$/) {
$val = $1;
$val =~ s/^=//;
$val = 1
if ($val eq "");
if ($ary) {
zprt("optdcd: PUSH val=%s\n",$val);
push(#$symlhs,$val);
}
else {
zprt("optdcd: SET val=%s\n",$val);
$$symlhs = $val;
}
$match = 1;
last;
}
}
sysfault("optdcd: unknown option -- '%s'\n",$arg)
unless ($match);
}
}
sub dosum
{
my($bf);
my(#rhs);
my(#n);
zprtx("\n")
if ($opt_clip);
$xfdst = xfopen(">$tmpfile","dosum");
# get count of sequence values (i.e. "n")
foreach $bf (#body) {
#rhs = split(" ",$bf);
push(#n,#rhs);
}
printf($xfdst "%d\n",scalar(#n));
foreach $bf (#body) {
zprtx("dosum: %s\n",$bf)
if ($opt_clip);
print($xfdst $bf,"\n");
}
$xfdst = xfclose($xfdst);
# run program
my($outval) = (`./$sroot < $tmpfile`);
chomp($outval);
# output test input data and program output
outf("\n");
outf("----------\n")
if ($opt_clip);
outf("Input:\n");
outf("```\n")
if ($opt_clip);
$xfsrc = xfopen("<$tmpfile","dosum");
while ($buf = <$xfsrc>) {
outf("%s",$buf);
}
$xfsrc = xfclose($xfsrc);
outf("```\n")
if ($opt_clip);
outf("\n")
if ($opt_clip);
outf("Output: %d\n",$outval);
undef(#body);
}
sub outf
{
printf($xfout #_);
}
sub zprt
{
goto &zprtx
if ($opt_d);
}
sub zprtx
{
printf(STDERR #_);
}
sub sysfault
{
zprtx(#_);
exit(1);
}
sub xfopen
{
my($file,$who) = #_;
my($xf);
open($xf,$file) or
sysfault("xfopen: unable to open '%s' -- $!\n",$file);
$xf;
}
sub xfclose
{
my($xf) = #_;
close($xf);
undef($xf);
$xf;
}
sub vxsystem
{
my($cmd);
$cmd = join(" ",#_);
system($cmd);
$? >> 8;
}
package seq;
__DATA__
-2 -1 1 2
1 1 1 1 1
7 19
2 4 6 8 11 14 17 9
8 6 4 2 11 14 15 16
1 2 3 4
2 3 4 5
3 4 5 6
2 1
UPDATE:
Here is a version that adds some debug printing (-DDEBUG). And, selection of <= vs < (-DLE).
I've updated the runseq script above to handle this version [it is backwards compatible].
#include <stdio.h>
#if DEBUG
#define dbgprt(_fmt...) \
fprintf(stderr,_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
int
main(void)
{
// get count of sequence numbers
int n;
scanf("%d", &n);
// length of current sequence
int curlen = 0;
// sum of current sequence
int cursum = 0;
// value of current number
int curval;
// value of previous number
int oldval = 0;
// get the first number
scanf("%d", &curval);
// add it to the current sequence
curlen += 1;
cursum += curval;
dbgprt("OLD: oldval=%d curval=%d cursum=%d curlen=%d\n",
oldval,curval,cursum,curlen);
oldval = curval;
// initialize the best sequence from the current one
int bestsum = cursum;
int bestlen = curlen;
// get all remaining numbers in the sequence
for (int i = 1; i < n; ++i, oldval = curval) {
// get new current number
if (scanf("%d", &curval) != 1) {
fprintf(stderr, "too short\n");
break;
}
// reset the current sequence if we're not increasing
#if LE
if (curval <= oldval) {
cursum = 0;
curlen = 0;
dbgprt("ZAPLE\n");
}
#else
if (curval < oldval) {
cursum = 0;
curlen = 0;
dbgprt("ZAPLT\n");
}
#endif
// add to the current sequence
cursum += curval;
curlen += 1;
dbgprt("CUR: oldval=%d curval=%d cursum=%d curlen=%d\n",
oldval,curval,cursum,curlen);
// save off the longest sequence we've seen
if (curlen > bestlen) {
dbgprt("NEWLEN\n");
bestlen = curlen;
bestsum = cursum;
continue;
}
// save off a sequence that is the same length as the best but has a
// larger sum
if ((curlen == bestlen) && (cursum > bestsum)) {
dbgprt("NEWSUM\n");
bestsum = cursum;
continue;
}
}
// print the final/best sum
printf("%d\n", bestsum);
return 0;
}

Related

Can anyone explain this code? "Chef and Dolls"(Problem Code: MISSP) on codechef.com. got it from some one else

#include <stdio.h>
int main(void)
{
int t,n,a,res;
scanf("%d",&t);
while(t--)
{
res=0;
scanf("%d",&n);
while(n--)
{
scanf("%d",&a);
res^=a;
}
printf("%d\n",res);
}
return 0;
}
Input:
1
3
1
2
1
Output:2
Input:
1
9
1
2
3
4
5
1
4
3
2
Output:5
The objective is to find the odd one that has no pair in the input, the first line is the number of test cases, the second line is the size of the data set. I don't understand how its giving the correct result.
I did the same question in a different manner->
#include <stdio.h>
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,t[100001]={0},p;
scanf("%d",&n);
int d[n];
for(int i=0;i<n;i++)
{
scanf("%d",&d[i]);
t[d[i]]++;
}
for(int i=0;i<n;i++)
{
if(t[d[i]]%2==1)
{
printf("%d\n",d[i]);
break;
}
}
}
return 0;
}
It works but I don't understand how the first one works....
Original:
You are correct to wonder ...
The XOR version does not work. It can work for certain inputs, but does not work in the general case.
Edit:
However, per Tom [thanks] (and a reread of the problem), we always have the "certain inputs".
Here are the additional rules:
The total number of dolls must be odd
Only one doll does not have a pair
So, we always have [even if the list is not sorted], the equivalent of the following [sorted] list:
X A A B B C C D D ...
where X is the "odd doll" and (e.g.) A, B, ... are the "other" dolls.
Any value XORed with itself is 0. So, all the pairs will cancel each other out (regardless of the order).
Thus, the above list is the equivalent of:
X 0 0 0 0 0
So, only X will remain.
I've revised the dotest script below. And, adjusted the test data.
Here is the cleaned up XOR source:
// xor.c -- XOR version (other) -- does not work
#include <stdio.h>
#include <stdlib.h>
#ifdef DEBUG
#define dbgprt(_fmt...) printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
int
main(int argc,char **argv)
{
int t, n, a, res;
FILE *fin;
if (argc < 2)
fin = stdin;
else
fin = fopen(argv[1],"r");
fscanf(fin,"%d", &t);
while (t--) {
res = 0;
fscanf(fin,"%d", &n);
while (n--) {
if (fscanf(fin,"%d", &a) != 1) {
printf("premature EOF\n");
exit(1);
}
res ^= a;
dbgprt("DBG res=%d a=%d\n",res,a);
}
printf("%d\n", res);
}
fclose(fin);
return 0;
}
Here is your [cleaned up] frequency table source:
// freq.c -- frequency counting (OP's code)
#include <stdio.h>
#include <stdlib.h>
#ifdef DEBUG
#define dbgprt(_fmt...) printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
int
main(int argc,char **argv)
{
int T;
FILE *fin;
if (argc < 2)
fin = stdin;
else
fin = fopen(argv[1],"r");
fscanf(fin,"%d", &T);
while (T--) {
int n,
t[100001] = { 0 }, p;
fscanf(fin,"%d", &n);
int d[n];
for (int i = 0; i < n; i++) {
if (fscanf(fin,"%d", &d[i]) != 1) {
printf("premature EOF\n");
exit(1);
}
t[d[i]]++;
dbgprt("scanf: i=%d d=%d t=%d\n",i,d[i],t[d[i]]);
}
for (int i = 0; i < n; i++) {
dbgprt("final: i=%d d=%d t=%d\n",i,d[i],t[d[i]]);
if (t[d[i]] % 2 == 1) {
printf("%d\n", d[i]);
break;
}
}
}
fclose(fin);
return 0;
}
Here is a perl script that generates test cases:
Edit: Revised to add the restriction of a odd number of dolls.
#!/usr/bin/perl
# dotest2 -- run chef and dolls test
#
# options:
# "-C" -- count of numbers per test
# "-T" -- number of tests (DEFAULT: 10)
# "-R" -- random number seed (DEFAULT: 12345)
# "-e" -- stop on test error
# "-gdb" -- run program under gdb
#
# arguments:
# 1-- list of programs to test (DEFAULT: *.c)
master(#ARGV);
exit(0);
# master -- master control
sub master
{
my(#argv) = #_;
optdcd(\#argv,"opt_gdb","opt_T","opt_C","opt_R","opt_e");
$opt_R //= 12345;
srand($opt_R);
zprtx("R=%d\n",$opt_R);
$datfile = "biginp";
zprtx("input=%s\n",$datfile);
open($xfout,">$datfile") or
die("unable to open '$datfile' -- $!\n");
$opt_T //= int(rand(10)) + 1;
outf("%d\n",$opt_T);
zprtx("T=%d\n",$opt_T);
$cmax = 100000;
$opt_C //= $cmax;
$opt_C = $cmax
if ($opt_C > $cmax);
for ($tcur = 1; $tcur <= $opt_T; ++$tcur) {
dogen();
}
close($xfout);
opendir($xfdir,".");
while (1) {
$pgm = readdir($xfdir);
last unless (defined($pgm));
push(#pgm,$pgm)
if ($pgm =~ s/[.]c$//);
}
close($xfdir);
push(#argv,#pgm)
if (#argv <= 0);
foreach $pgm (#argv) {
dopgm();
}
}
sub dogen
{
my(#dup);
my($ocnt);
$arrcnt = int(rand($opt_C)) + 1;
$arrcnt |= 1;
outf("\n%d\n",$arrcnt);
# get the unique value
$single = int(rand(100001));
# get the index to inject
###$injidx = int(rand($arrcnt));
outf(" %d\n",$single);
++$ocnt;
zprtx("dogen: single=%d arrcnt=%d\n",$single,$arrcnt);
push(#exp,$single);
$npair = int($arrcnt / 2);
for ($idx = 0; $idx < $npair; ++$idx) {
while (1) {
$dup = int(rand(100001));
last if ($dup != $single);
}
push(#dup,$dup);
}
for ($idx = 0; ; ++$idx) {
last if ($ocnt >= $arrcnt);
$dup = $dup[$idx % $npair];
outf(" %d\n",$dup);
++$ocnt;
}
}
sub dopgm
{
zprtx("\n");
zprtx("dopgm: %s\n",$pgm);
zprtx("cc ...\n");
$code = doexec("cc","-g","-o",$pgm,"$pgm.c");
exit(1) if ($code);
if ($opt_gdb) {
dogdb();
}
else {
docmp();
}
}
sub docmp
{
zprtx("run $pgm $datfile ...\n");
#act = (`./$pgm $datfile`);
$status = $?;
$code = $status >> 8;
zprtx("%d lines\n",scalar(#act));
if ($code) {
zprtx("fault code=%d status=%8.8X\n",$code,$status);
exit(1);
}
$idx = -1;
foreach $exp (#exp) {
++$idx;
$act = $act[$idx];
chomp($act);
$pass = ($act == $exp);
printf("dopgm: %s exp=%d act=%d -- %s\n",
$pgm,$exp,$act,$pass ? "PASS" : "FAIL");
if ($opt_e) {
exit(1) unless ($pass);
}
}
}
sub dogdb
{
zprtx("gdb ...\n");
open($xfgdb,">cmds") or
die("dogdb: unable to open 'cmds' -- $!\n");
printf($xfgdb "set args %s\n",$datfile);
close($xfgdb);
doexec("gdb","-x","cmds","./$pgm");
}
# optdcd -- decode command line options
sub optdcd
{
my(#syms) = #_;
my($argv);
my($arg);
my($sym,$val,$match);
$argv = shift(#syms);
# get options
while (#$argv > 0) {
$arg = $argv->[0];
last unless ($arg =~ /^-/);
shift(#$argv);
$match = 0;
foreach $sym (#syms) {
$opt = $sym;
$opt =~ s/^opt_/-/;
if ($arg =~ /^$opt(.*)$/) {
$val = $1;
$val =~ s/^=//;
$val = 1
if ($val eq "");
$$sym = $val;
$match = 1;
last;
}
}
sysfault("optdcd: unknown option -- '%s'\n",$arg)
unless ($match);
}
}
sub outf
{
printf($xfout #_);
}
sub doexec
{
$cmd = join(" ",#_);
system($cmd);
$code = $? >> 8;
$code;
}
sub zprtx
{
printf(#_);
}
Here is the output of ./dotest2 -C20 -T10:
R=12345
input=biginp
T=10
dogen: single=91919 arrcnt=5
dogen: single=90649 arrcnt=15
dogen: single=12698 arrcnt=21
dogen: single=26591 arrcnt=13
dogen: single=2026 arrcnt=11
dogen: single=29902 arrcnt=1
dogen: single=44366 arrcnt=21
dogen: single=12315 arrcnt=15
dogen: single=55435 arrcnt=19
dogen: single=11214 arrcnt=11
dopgm: freq
cc ...
run freq biginp ...
10 lines
dopgm: freq exp=91919 act=91919 -- PASS
dopgm: freq exp=90649 act=90649 -- PASS
dopgm: freq exp=12698 act=12698 -- PASS
dopgm: freq exp=26591 act=26591 -- PASS
dopgm: freq exp=2026 act=2026 -- PASS
dopgm: freq exp=29902 act=29902 -- PASS
dopgm: freq exp=44366 act=44366 -- PASS
dopgm: freq exp=12315 act=12315 -- PASS
dopgm: freq exp=55435 act=55435 -- PASS
dopgm: freq exp=11214 act=11214 -- PASS
dopgm: xor
cc ...
run xor biginp ...
10 lines
dopgm: xor exp=91919 act=91919 -- PASS
dopgm: xor exp=90649 act=90649 -- PASS
dopgm: xor exp=12698 act=12698 -- PASS
dopgm: xor exp=26591 act=26591 -- PASS
dopgm: xor exp=2026 act=2026 -- PASS
dopgm: xor exp=29902 act=29902 -- PASS
dopgm: xor exp=44366 act=44366 -- PASS
dopgm: xor exp=12315 act=12315 -- PASS
dopgm: xor exp=55435 act=55435 -- PASS
dopgm: xor exp=11214 act=11214 -- PASS
Here is the generated input file:
10
5
91919
20684
72478
20684
72478
15
90649
34796
85788
41518
19416
68561
52438
15963
34796
85788
41518
19416
68561
52438
15963
21
12698
433
38269
25079
65529
53449
60997
28786
90927
73613
12110
433
38269
25079
65529
53449
60997
28786
90927
73613
12110
13
26591
94536
42469
24835
67730
7120
45574
94536
42469
24835
67730
7120
45574
11
2026
88618
65458
55970
98505
33945
88618
65458
55970
98505
33945
1
29902
21
44366
12912
91504
38642
3043
18444
93569
48079
59784
43615
10501
12912
91504
38642
3043
18444
93569
48079
59784
43615
10501
15
12315
67212
3399
96444
1952
4466
42123
76422
67212
3399
96444
1952
4466
42123
76422
19
55435
61717
64651
38567
90212
32288
42315
45495
57224
4846
61717
64651
38567
90212
32288
42315
45495
57224
4846
11
11214
84260
38638
3674
74480
50266
84260
38638
3674
74480
50266

Infinite loop subset sum backtracking

I'm trying to implement my own version of the sum of subsets problem, using backtracking, to get all the possible solutions of obtaining a given sum from an array of elements. At the moment, I'm getting output stuck in an infinite, the output adds up to the sum that I want, but it exceeds the number of elements of a type available in the array. I'm not sure why this happens, because I put some stopping conditions. The code:
#include <stdio.h>
#define MAX 1024
int coins_array[] = {1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,10,10,10,10,10,15,15,15,15,15,15};
int N = sizeof(coins_array) / sizeof(coins_array[0]);
int S = 27, Sol[MAX], sum, sol;
int acceptable(int step)
{
int i = 0, sum = 0;
for(i = 1; i <= step; i++)
{
sum += Sol[i];
}
if((sum <= S) && (step <= N))
return 1;
return 0;
}
int solution(int sum)
{
if (sum == S)
return 1;
return 0;
}
void print_solution(int step)
{
int i;
for(i = 1 ; i <= step ; ++i)
printf("%d ",Sol[i]);
printf("\n");
}
void back(int step)
{
int i;
for(i = 0; i < N; i++)
{
Sol[step] = coins_array[i];
sum += coins_array[i];
if(acceptable(step) == 1)
{
if(solution(sum) == 1)
{
print_solution(step);
}
else
back(step+1);
}
sum -= coins_array[i];
}
}
int main()
{
back(1);
return 0;
}
Output (in an infinite loop):
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3
So, the numbers add up to the desired sum, however it exceeds the number of available 1's, and doesn't make use of 10 or 15. I ran to this in the debugger and I believe the problem for the loop is at back(step+1). Any idea how I could fix this?
Not sure this covers all problems in your code but it's at least its one bug that needs to be fixed.
Your current code uses the same coin several times. For instance if you set the target to be 2 (i.e. S = 2), your code will generate a solution where coins_array[0] is used twice.
This happens because your back function always starts looking at the coins_array from index zero.
void back(int step)
{
int i;
for(i = 0; i < N; i++)
^^^^^
Always starting from zero is wrong
Instead you need to start from the "next unused" coin. Unfortunately your current code doesn't track that so you need to redesign your solution.
To show the above described problem I made some minor changes to your program - 1) Reduced the available coins 2) Changed the target value 3) Added an array to track which coin (aka index) was used 4) printed the index
So with these change your code looks like:
#define MAX 1024
int coins_array[] = {1,1,3};
int N = sizeof(coins_array) / sizeof(coins_array[0]);
int S = 2, Sol[MAX], IndexUsed[MAX], sum, sol;
int acceptable(int step)
{
int i = 0, sum = 0;
for(i = 1; i <= step; i++)
{
sum += Sol[i];
}
if((sum <= S) && (step <= N))
return 1;
return 0;
}
int solution(int sum)
{
if (sum == S)
return 1;
return 0;
}
void print_solution(int step)
{
int i;
for(i = 1 ; i <= step ; ++i)
printf("%d (%d) ",Sol[i], IndexUsed[i]);
printf("\n");
}
void back(int step)
{
int i;
for(i = 0; i < N; i++)
{
Sol[step] = coins_array[i];
IndexUsed[step] = i;
sum += coins_array[i];
if(acceptable(step) == 1)
{
if(solution(sum) == 1)
{
print_solution(step);
}
else
back(step+1);
}
sum -= coins_array[i];
}
}
int main()
{
back(1);
return 0;
}
and generates the output (with my comments added):
1 (0) 1 (0) // Illegal - coin at index 0 used twice
1 (0) 1 (1) // Legal - coin at index 0 and 1 used to reach the sum 2
1 (1) 1 (0) // Illegal - this combination have already been used
1 (1) 1 (1) // Illegal - coin at index 1 used twice
As you can see, your code prints 4 solutions but it should only have printed 1. As already stated, this happens because your code always start from index zero in the function back

Finding certain combination in a text file

I have a text file of combinations without repetition of 6 number ranging from 1 to 10, like this:
2 3 8 9 6 4
8 3 1 4 7 9
1 3 5 7 6 9
1 5 7 9 8 4
1 3 5 4 8 7
2 4 6 8 7 1
6 7 8 3 5 9
3 1 6 2 7 9
1 7 4 2 5 8
3 4 9 2 1 7
...
and I have a gold combination, let's say: 2, 1, 3, 9, 8, 5
I want to check how many times I have a combination in my text file that matches 5 numbers of the gold combination. This is my code attempt:
// Including C Standard Libraries
#include <stdint.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
// Gold Combination
int n1 = 2;
int n2 = 1;
int n3 = 3;
int n4 = 9;
int n5 = 8;
int n6 = 5;
// Numbers of Matching Combinations
int match_comb = 0;
// Creating a file to see combinations content
char ch, file_name[25];
FILE *fp;
fp = fopen("combinations.txt", "r"); // Read Mode
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
int j = 0;
int mn = 0; // Number of matched numbers
int x[6] = {0,0,0,0,0,0};
char c;
while((c = fgetc(fp)) != EOF)
{
if(c == ' ' || c == '\n')
{
}
else
{
x[j] = c;
if (j == 5)
{
if(x[0]==n1 || x[0]==n2 || x[0]==n3 || x[0]==n5 || x[0]==n6){
mn += 1;
}if(x[1]==n1 || x[1]==n2 || x[1]==n3 || x[1]==n5 || x[1]==n6){
mn += 1;
}if(x[2]==n1 || x[2]==n2 || x[2]==n3 || x[2]==n5 || x[2]==n6){
mn += 1;
}if(x[3]==n1 || x[3]==n2 || x[3]==n3 || x[3]==n5 || x[3]==n6){
mn += 1;
}if(x[4]==n1 || x[4]==n2 || x[4]==n3 || x[4]==n5 || x[4]==n6){
mn += 1;
}if(x[5]==n1 || x[5]==n2 || x[5]==n3 || x[5]==n5 || x[5]==n6){
mn += 1;
}
if ( mn == 5)
{
match_comb += 1; // Adding One the the Match Combinantions counter
}
for (int i = 0; i < 6; ++i) // Resetting x array
{
x[i] = 0;
}
mn = 0; // Resetting
j = -1; // Resetting j
}
j += 1;
}
}
printf("Number of Matching Combinations:");
printf("%d", match_comb);
printf("\n");
fclose(fp);
return 0;
}
But, I think the code is not working, because it always says that there are 0 matched combinations .. Are there ways to simplify or make my code work?
also, this only works for the case of numbers with one digit, but in the case I have bigger range, let's say 1-20, I am not really sure how to gather the numbers from the text file .. I was thinking in a condition where there was a counter after every space, if the counter is one, take the character as a number of one digit, if the counter is two, gather the two characters and do something to tell the code to gather the two characters and use the resulted number, but I don't know how to do that ..
Edit:
int main()
{
// Gold Combination
int n1 = 20;
int n2 = 1;
int n3 = 35;
int n4 = 9;
int n5 = 18;
int n6 = 5;
// Numbers of Matching Combinations
int match_comb = 0;
// Creating a file to see combinations content
char ch, file_name[25];
FILE *fp;
fp = fopen("combinations.txt", "r"); // Read Mode
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
int j = 0;
int mn = 0; // Number of matched numbers
int x[6] = {0,0,0,0,0,0};
int c;
while((c = fgetc(fp)) != EOF)
{
//x[j] = fscanf(fp, "%d", &c);
fscanf(fp, "%d %d %d %d %d %d", &x[0], &x[1], &x[2], &x[3], &x[4], &x[5]);
printf("%d", x[0]);
printf(" ");
printf("%d", x[1]);
printf(" ");
printf("%d", x[2]);
printf(" ");
printf("%d", x[3]);
printf(" ");
printf("%d", x[4]);
printf(" ");
printf("%d", x[5]);
if(x[0]==n1 || x[0]==n2 || x[0]==n3 || x[0]==n5 || x[0]==n6){
mn += 1;
}if(x[1]==n1 || x[1]==n2 || x[1]==n3 || x[1]==n5 || x[1]==n6){
mn += 1;
}if(x[2]==n1 || x[2]==n2 || x[2]==n3 || x[2]==n5 || x[2]==n6){
mn += 1;
}if(x[3]==n1 || x[3]==n2 || x[3]==n3 || x[3]==n5 || x[3]==n6){
mn += 1;
}if(x[4]==n1 || x[4]==n2 || x[4]==n3 || x[4]==n5 || x[4]==n6){
mn += 1;
}if(x[5]==n1 || x[5]==n2 || x[5]==n3 || x[5]==n5 || x[5]==n6){
mn += 1;
}
if ( mn == 5)
{
match_comb += 1; // Adding One the the Match Combinantions counter
}
for (int i = 0; i < 6; ++i) // Resetting x array
{
x[i] = 0;
}
mn = 0; // Resetting
printf("\n");
}
printf("Number of Matching Combinations:");
printf("%d", match_comb);
printf("\n");
fclose(fp);
return 0;
}
The problem lies with:
x[j] = c;
This assigns a char to an integer. You need to convert c to an integer. For example by subtracting the character code of zero:
x[j] = c-'0';
You can use isdigit(c) to check whether c is really a digit.
Either with the help of the debugger or by using printf to show the exact values of the x[0], x[1], ... you get a clearer view of what was going wrong.
As for reading numbers of more than 1 digit, the best idea is to use a function such as fscanf(fp, "%d", &c) which automatically converts the read characters to a number. Note that if you use &c here, c needs to be an int, not a char.
If you want to work with fscanf, you need to remove the calls to fgetc (in your while-loop), because otherwise fgetc everytime removes a character. Removing a character is no problem when that's a space or a newline, but it is a problem for the first digit in the line. When fgetc can not be used anymore for checking end-of-file, use the return value of fscanf as explained in this post. For example:
while (true) // endless loop, but will end via a 'break'
{
// remove if(c == ' ' || c == '\n')
if (fscanf(fp, "%d", &c) != 1) // check whether fscanf found 1 input
break; // this jumps out of the while loop
.... // rest of your code
}
If you really want to use fgetc for reading the numbers, you need something like:
if (isdigit(c))
num = num * 10 + (c - '0');
and not yet putting num in the X-array until you encounter a non-digit. num needs to be reset to 0 thereafter.
As for the code you use for calculating the number of matches, it looks quite clever if you're fully new to programming. An improvement would be to also put the n values in an array and to use for-loops to check the number of matches.

Wanted to check if a credit card number is valid or not

I wanted to check if a credit card number is valid or not but when i run the code, every number I give as input, the output comes as invalid.
The example given below is what I should i do.
Example with David’s Visa: 4003600000000014.
For the sake of discussion, let’s first underline every other digit, starting with the number’s second-to-last digit:
4003600000000014
Okay, let’s multiply each of the underlined digits by 2:
1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2
That gives us:
2 + 0 + 0 + 0 + 0 + 12 + 0 + 8
Now let’s add those products’ digits (i.e., not the products themselves) together:
2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13
Now let’s add that sum (13) to the sum of the digits that weren’t multiplied by 2 (starting from the end):
13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20
, the last digit in that sum (20) is a 0, so David’s card is legit!
#include <stdio.h>
int main()
{
int no;
printf("Visa number: ");`
scanf("%d", &no);
int d_1, d_2, d_3, d_4, d_5, d_6, d_7, d_8, d_9, d_10, d_11, d_12, d_13, d_14, d_15;
d_15 = no%10;
d_14 = ((no%100)/10)*2;
d_13 = (no%1000)/100;
d_12 = ((no%10000)/1000)*2;
d_11 = (no%100000)/10000;
d_10 = ((no%1000000)/100000)*2;
d_9 = (no%10000000)/1000000;
d_8 = ((no%100000000)/10000000)*2;
d_7 = (no%1000000000)/100000000;
d_6 = ((no%10000000000)/1000000000)*2;
d_5 = (no%100000000000)/10000000000;
d_4 = ((no%1000000000000)/100000000000)*2;
d_3 = (no%10000000000000)/1000000000000;
d_2 = ((no%100000000000000)/10000000000000)*2;
d_1 = (no%1000000000000000)/100000000000000;
int d[7] = {d_2, d_4, d_6, d_8, d_10, d_12, d_14};
int n,add;
for (n=1; n<=7; n++)
if(d[n]>10)
{
d[n] = (d[n]%10);
d[(15-n)+1] = ((d[n]%100)/10);
int sum=0;
for (int i=0; i<7; i++)
sum += d[i];
}
else
{
add = d_14 + d_12 + d_10 + d_8 + d_6 + d_4 + d_2;
}
int sum = add + d_15 + d_13 + d_11 + d_9 + d_7 + d_5 + d_3 + d_1;
if ((sum % 10) == 0)
{
printf("%s\n", "The card is valid");
}
else
{
printf("%s\n", "The card is invalid");
}
}
every number I give as input, the output comes as invalid.
Too big
OP's int is likely 32-bit.
Reading text input that would attempt to form an int outside the int range is undefined behavior. Rest of code is irrelevant.
int no;
scanf("%d", &no); // attempt to read "4003600000000014" leads to UB.
Consider reading user input into a string first and then process the characters. #Weather Vane
char buf[100];
if (fgets(buf, sizeof buf, stdin)) {
int i;
sum[2] = { 0, 0 }; // sums of even indexed digits and odd indexed digits.
// Note: only 1 sum really needed, but using 2 sums to mimic OP's approach
for (i = 0; isdigit((unsigned char) buf[i]); i++) {
digit = buf[i] - '0';
if (i%2 == 0) {
digit *= 2;
if (digit >= 10) {
digit = (digit/10 + digit%10);
}
}
sum[i%2] += digit;
}
// reject bad input: too long or missing expected end
if (i > 16 || (buf[i] != '\n' && buf[i] != '\0')) {
puts("Bad input");
} else {
// pseudo code to not give everything away.
// do math on sum[0], sum[1]
// if as expected --> success
}
}
#include <stdio.h>
#include <cs50.h>
long credit;
int getting_the_final_total_number (void);
void checking_which_kind (void);
int main(void)
{
credit = get_long("Number: ");
int i = 0;
long number_count = credit;
//finding how many numbers are there.
while(number_count > 0)
{
number_count /= 10;
i++;
}
//we use and because (using or make once true, the code block will work and always telling INVALID)
if(i != 13 && i != 15 && i != 16)
{
printf("INVALID\n");
return 0;
}
int total = getting_the_final_total_number(); //adding sum_1 and sum_2
if(total % 10 != 0)
{
printf("INVALID\n");
return 0;
}
checking_which_kind();
}
//assigning the credit to another variable for the loop
int getting_the_final_total_number (void)
{
long credit_one = credit;
int mod_1;
int mod_2;
int sum_1 = 0;
int m;
int d;
int sum_2 = 0;
do
{
//cutting the number into two pieces with all the last numbers and all the second-last-numbers
//cutting the last numbers.
mod_1 = credit_one % 10;
credit_one = credit_one / 10;
sum_1 += mod_1;
//cutting the second-last-numbers.
mod_2 = credit_one % 10;
credit_one = credit_one / 10;
//doubling the mod_2 (the second-last-numbers)
mod_2 = mod_2 * 2;
//making them into one number (if there is 16 or 18 in the product then make them 1 and 6 or 1 and 8. After that add them all together ).
m = mod_2 % 10; //This is for only one standing numer like 1 or 2 or 9 etc (but no 12 or 14 or 16)
d = mod_2 / 10; //This is for ten's digit to make sure to become ONE standing digit
sum_2 = sum_2 + m + d;
}
while(credit_one > 0);
return sum_1 + sum_2;
}
//checking the first two number of credit
void checking_which_kind (void)
{
long cc = credit;
do
{
cc = cc / 10;
}
while(cc > 100);
if(cc / 10 == 5 && (cc % 10 > 0 || cc % 10 < 6))
{
printf("MASTERCARD\n");
}
else if(cc / 10 == 3 && (cc % 10 == 4 || cc % 10 == 7))
{
printf("AMERICAN EXPRESS\n");
}
else if(cc / 10 == 4 && cc % 10 >= 0)
{
printf("VISA\n");
}
else
{
printf("ERROR");
}
}

Is it possible to validate IMEI Number?

For a mobile shop application, I need to validate an IMEI number. I know how to validate based on input length, but is their any other mechanism for validating the input number? Is there any built-in function that can achieve this?
Logic from any language is accepted, and appreciated.
A search suggests that there isn't a built-in function that will validate an IMEI number, but there is a validation method using the Luhn algorithm.
General process:
Input IMEI: 490154203237518
Take off the last digit, and remember it: 49015420323751 & 8. This last digit 8 is the validation digit.
Double each second digit in the IMEI: 4 18 0 2 5 8 2 0 3 4 3 14 5 2 (excluding the validation digit)
Separate this number into single digits: 4 1 8 0 2 5 8 2 0 3 4 3 1 4 5 2 (notice that 18 and 14 have been split).
Add up all the numbers: 4+1+8+0+2+5+8+2+0+3+4+3+1+4+5+2 = 52
Take your resulting number, remember it, and round it up to the nearest multiple of ten: 60.
Subtract your original number from the rounded-up number: 60 - 52 = 8.
Compare the result to your original validation digit. If the two numbers match, your IMEI is valid.
The IMEI given in step 1 above is valid, because the number found in step #7 is 8, which matches the validation digit.
According to the previous answer from Karl Nicoll i'm created this method in Java.
public static int validateImei(String imei) {
//si la longitud del imei es distinta de 15 es invalido
if (imei.length() != 15)
return CheckImei.SHORT_IMEI;
//si el imei contiene letras es invalido
if (!PhoneNumber.allNumbers(imei))
return CheckImei.MALFORMED_IMEI;
//obtener el ultimo digito como numero
int last = imei.charAt(14) - 48;
//duplicar cada segundo digito
//sumar cada uno de los digitos resultantes del nuevo imei
int curr;
int sum = 0;
for (int i = 0; i < 14; i++) {
curr = imei.charAt(i) - 48;
if (i % 2 != 0){
// sum += duplicateAndSum(curr);
// initial code from Osvel Alvarez Jacomino contains 'duplicateAndSum' method.
// replacing it with the implementation down here:
curr = 2 * curr;
if(curr > 9) {
curr = (curr / 10) + (curr - 10);
}
sum += curr;
}
else {
sum += curr;
}
}
//redondear al multiplo de 10 superior mas cercano
int round = sum % 10 == 0 ? sum : ((sum / 10 + 1) * 10);
return (round - sum == last) ? CheckImei.VALID_IMEI_NO_NETWORK : CheckImei.INVALID_IMEI;
}
IMEI can start with 0 digit. This is why the function input is string.
Thanks for the method #KarlNicol
Golang
func IsValid(imei string) bool {
digits := strings.Split(imei, "")
numOfDigits := len(digits)
if numOfDigits != 15 {
return false
}
checkingDigit, err := strconv.ParseInt(digits[numOfDigits-1], 10, 8)
if err != nil {
return false
}
checkSum := int64(0)
for i := 0; i < numOfDigits-1; i++ { // we dont need the last one
convertedDigit := ""
if (i+1)%2 == 0 {
d, err := strconv.ParseInt(digits[i], 10, 8)
if err != nil {
return false
}
convertedDigit = strconv.FormatInt(2*d, 10)
} else {
convertedDigit = digits[i]
}
convertedDigits := strings.Split(convertedDigit, "")
for _, c := range convertedDigits {
d, err := strconv.ParseInt(c, 10, 8)
if err != nil {
return false
}
checkSum = checkSum + d
}
}
if (checkSum+checkingDigit)%10 != 0 {
return false
}
return true
}
I think this logic is not right because this working only for the specific IMEI no - 490154203237518 not for other IMEI no ...I implement the code also...
var number = 490154203237518;
var array1 = new Array();
var array2 = new Array();
var specialno = 0 ;
var sum = 0 ;
var finalsum = 0;
var cast = number.toString(10).split('');
var finalnumber = '';
if(cast.length == 15){
for(var i=0,n = cast.length; i<n; i++){
if(i !== 14){
if(i == 0 || i%2 == 0 ){
array1[i] = cast[i];
}else{
array1[i] = cast[i]*2;
}
}else{
specialno = cast[14];
}
}
for(var j=0,m = array1.length; j<m; j++){
finalnumber = finalnumber.concat(array1[j]);
}
while(finalnumber){
finalsum += finalnumber % 10;
finalnumber = Math.floor(finalnumber / 10);
}
contno = (finalsum/10);
finalcontno = Math.round(contno)+1;
check_specialno = (finalcontno*10) - finalsum;
if(check_specialno == specialno){
alert('Imei')
}else{
alert('Not IMEI');
}
}else{
alert('NOT imei - length not matching');
}
//alert(sum);
According to the previous answer from Karl Nicoll i'm created this function in Python.
from typing import List
def is_valid_imei(imei: str) -> bool:
def digits_of(s: str) -> List[int]:
return [int(d) for d in s]
if len(imei) != 15 or not imei.isdecimal():
return False
digits = digits_of(imei)
last = digits.pop()
for i in range(1, len(digits), 2):
digits[i] *= 2
digits = digits_of(''.join(map(str, digits)))
return (sum(digits) + last) % 10 == 0
This one is working for me
try:
immie_procesed = list(
map(int, str(request.data.decode("utf-8").split(',')[0])))
last_number = immie_procesed[len(immie_procesed) - 1]
val = sum([sum(map(int, str(int(v)*2))) if i % 2 else int(v)
for i, v in enumerate(immie_procesed[: -1])])
round_value = math.ceil(val / 10) * 10
validation_value = round_value - val
if (validation_value == last_number):
IMEI = request.data.decode("utf-8").split(',')[0]
else:
return "INVALID IMEI"
except:
return 'Something goes wrong in validation process'
I don't believe there are any built-in ways to authenticate an IMEI number. You would need to verify against a third party database (googling suggests there are a number of such services, but presumably they also get their information from more centralised sources).

Resources