Gentoo Linux and VIM worshiper, C developer, network protocol dissector implementer,socket/network programmer, recently entered the embedded world, hater of buzzwords and made up titles
#include<stdio.h>
#include<string.h>
#include<stdbool.h>// bool as string#define BOOL_STR(b) b ? "true" : "false"
// X/x checkstaticboolcheck_x(chard){if(d==88||d==120)returntrue;returnfalse;}// O/o checkstaticboolcheck_o(chard){if(d==79||d==111)returntrue;returnfalse;}staticboolcount_xo(constchar*d){// null pointerif(!d)returntrue;// get sizesize_tl=strlen(d);// no dataif(!l)returntrue;// res countersunsignedxc=0,oc=0;// mid pointunsignedmp=l/2,rm=l%2;// check for 88 (X) and 79 (O)// O(N/2)for(unsignedi=0,j=l-1;i<mp;i++,j--){// X counterxc+=check_x(d[i])+check_x(d[j]);// O counteroc+=check_o(d[i])+check_o(d[j]);}// remainderif(rm){// X counterxc+=check_x(d[mp+1]);// O counteroc+=check_o(d[mp+1]);}// resreturn(xc==oc?true:false);}intmain(void){// test stringsconstchar*str_00="ooxx";constchar*str_01="xooxx";constchar*str_02="ooxXm";constchar*str_03="zpzpzpp";constchar*str_04="zzoo";// resultsprintf("%s: %s\n",str_00,BOOL_STR(count_xo(str_00)));printf("%s: %s\n",str_01,BOOL_STR(count_xo(str_01)));printf("%s: %s\n",str_02,BOOL_STR(count_xo(str_02)));printf("%s: %s\n",str_03,BOOL_STR(count_xo(str_03)));printf("%s: %s\n",str_04,BOOL_STR(count_xo(str_04)));// no errorreturn0;}
Is it allowed to modify someone else’s solution? I think you made it a bit more complicated than necessary. Anyone please correct me if I’m wrong:
C strings end with the null character '\0', so you can skip getting the string length and do a while loop that checks for the null character (strlen does just that anyway);
I didn’t really understand why you’re walking the string from the start and the middle, instead of from beginning to end, so I changed it;
since we then only test for x and o once, I could inline the tests;
xc == oc and d == 88 || d == 120 are already boolean expressions, so you don’t need the ternary operator ... ? true : false or an if(...) return true; else return false;;
since I never used assertions in C, I took the opportunity to try them for the test cases (I intentionally wrote assert(count_xo("xooxx") == false) in the tests instead of assert(! count_xo("xooxx")) for consistency and readability.
#include <stdio.h>
#include <stdbool.h>
// bool as string#define BOOL_STR(b) b ? "true" : "false"
staticboolcount_xo(constchar*d){// null pointerif(!d)returntrue;// countersunsignedxc=0,oc=0,i=-1;while(d[++i]!='\0'){// X counterif(d[i]==88||d[i]==120)xc++;// O counterif(d[i]==79||d[i]==111)oc++;}// resreturnxc==oc;}intmain(void){// test stringsassert(count_xo("ooxx")==true);assert(count_xo("xooxx")==false);assert(count_xo("ooxXm")==true);assert(count_xo("zpzpzpp")==true);assert(count_xo("zzoo")==false);assert(count_xo("xoffxffo")==true);return0;}
Gentoo Linux and VIM worshiper, C developer, network protocol dissector implementer,socket/network programmer, recently entered the embedded world, hater of buzzwords and made up titles
The loop tests strings from both sides to be more performant. Try doing benchmarks of both versions and post the results. I don't have time right now but might do it in the evening and show you the difference. Or, I might just embarrass myself lol.
Gentoo Linux and VIM worshiper, C developer, network protocol dissector implementer,socket/network programmer, recently entered the embedded world, hater of buzzwords and made up titles
I wrote this too fast without even thinking too much, so once again, I appreciate your comment. Anyway, I know that inlining helps, but speed wasn't on my priority list for this challenge. :)
Here are my results:
Your code: ~550 nsec
My code: ~1140 nsec
Thumbs up for faster code.
P.S.
I suspected that strlen might be the culprit, and I was right.
If I change the code like this, I get results similar to yours, around 500 nsec more/less
staticboolcount_xo(constchar*d,size_tl){// null pointerif(!d)returntrue;// no dataif(!l)returntrue;// res countersunsignedxc=0,oc=0;// mid pointunsignedmp=l/2,rm=l%2;// check for 88 (X) and 79 (O)// O(N/2)for(unsignedi=0,j=l-1;i<mp;i++,j--){// X counterxc+=check_x(d[i])+check_x(d[j]);// O counteroc+=check_o(d[i])+check_o(d[j]);}// remainderif(rm){// X counterxc+=check_x(d[mp+1]);// O counteroc+=check_o(d[mp+1]);}// resreturnxc==oc;}
Gentoo Linux and VIM worshiper, C developer, network protocol dissector implementer,socket/network programmer, recently entered the embedded world, hater of buzzwords and made up titles
Gentoo Linux and VIM worshiper, C developer, network protocol dissector implementer,socket/network programmer, recently entered the embedded world, hater of buzzwords and made up titles
Well that's C, just how it is, you either hate it or you love it 😁. I missed a comma there; what I wanted to say was: guys, please don't kill me, this is C and it's gonna get ugly.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
C 😱 don't kill me please
Results:
Is it allowed to modify someone else’s solution? I think you made it a bit more complicated than necessary. Anyone please correct me if I’m wrong:
C strings end with the null character
'\0'
, so you can skip getting the string length and do a while loop that checks for the null character (strlen
does just that anyway);I didn’t really understand why you’re walking the string from the start and the middle, instead of from beginning to end, so I changed it;
since we then only test for
x
ando
once, I could inline the tests;xc == oc
andd == 88 || d == 120
are already boolean expressions, so you don’t need the ternary operator... ? true : false
or anif(...) return true; else return false;
;since I never used assertions in C, I took the opportunity to try them for the test cases (I intentionally wrote
assert(count_xo("xooxx") == false)
in the tests instead ofassert(! count_xo("xooxx"))
for consistency and readability.Hi and no problem changing the code
The following is indeed not needed:
The loop tests strings from both sides to be more performant. Try doing benchmarks of both versions and post the results. I don't have time right now but might do it in the evening and show you the difference. Or, I might just embarrass myself lol.
Cheers
I wrote this too fast without even thinking too much, so once again, I appreciate your comment. Anyway, I know that inlining helps, but speed wasn't on my priority list for this challenge. :)
Here are my results:
Your code: ~550 nsec
My code: ~1140 nsec
Thumbs up for faster code.
P.S.
I suspected that
strlen
might be the culprit, and I was right.If I change the code like this, I get results similar to yours, around 500 nsec more/less
Nice. I didn’t inline for speed, but for compactness, so that people don’t say C is too complicated, so verbose, etc. :-)
C is my baby, just started embedded C on SBCs, mostly arm 32bit. And people will always say that 🤣👍
I feel like the C might've already done you in? dang, that's some verbose low-level lang 😶
Well that's C, just how it is, you either hate it or you love it 😁. I missed a comma there; what I wanted to say was: guys, please don't kill me, this is C and it's gonna get ugly.