5
\$\begingroup\$

I could not think of a better title.

This is a tips question. I'm asking for tips on golfing my code.

I recently took part in a code golf competition in C. The competition ended and I lost. The problem is:

Input a line with a number n.

Then input n lines, each line contains only a set of cards in descending order, e. g. X2AAKKKKQT9765433 or DX22AKKQJTT884443. Figure out if it contains DX or four of the same cards in a row.

Obviously, this is a chameleon challenge (finding DX is essentially the same as checking the second character if it is X, and to check for four of the same cards you only need to check the first and the last card of the quadruplet, because the cards are in descending order.)

In that competition, the input format is strict, and error-terminating is disallowed.

After the competition, we continued to improve on this problem. We've got this so far (98 bytes):

char*p,s[99];main(){for(gets(s);gets(p=s);puts(s[1]>87?"Yes":"No"))for(;*p;)s[1]|=*p^p++[3]?0:88;}

I'm looking for tips to golf this down further.

\$\endgroup\$
2
  • \$\begingroup\$ I considered main function recursion to no avail. \$\endgroup\$ Commented Aug 7, 2022 at 15:49
  • 5
    \$\begingroup\$ What do the D and X stand for? I can only guess that one of them represents a joker. \$\endgroup\$ Commented Aug 7, 2022 at 19:32

1 Answer 1

7
\$\begingroup\$

94 bytes

Instead of increasing s[1] when you find a quadruplet, setting it to zero is a bit cheaper. The conditional in puts stays the same length:

char*p,s[99];main(){for(gets(s);gets(p=s);puts(s[1]%88?"No":"Yes"))for(;*p;)s[1]*=*p!=p++[3];}

Try it online!

dingledooper suggested two more improvements:

93 bytes

If we can avoid to produce in the first iteration, The initial call to gets can be dropped. This is achieved by assuming the first argument to main (argc) is 1, which is the case if there are no command line arguments.

char*p,s[99];main(i){for(;gets(p=s);--i&&puts(s[1]%88?"No":"Yes"))for(;*p;)s[1]*=*p!=p++[3];}

Try it online!

87 bytes

If you stop the inner for loop as soon a quadruplet is found or the end of input is reached, *p>0 indicates a quadruplet:

char*p,s[99];main(i){for(;gets(p=s);--i&&puts(s[1]>87|*p?"Yes":"No"))for(;*p++-p[2];);}

Try it online!

\$\endgroup\$
6
  • \$\begingroup\$ You can also just enter s[] rather than s[99]. It worked in the tests cases \$\endgroup\$
    – TKirishima
    Commented Aug 7, 2022 at 17:16
  • \$\begingroup\$ @TKirishima For me, I get error: array size missing in 's'. \$\endgroup\$
    – naffetS
    Commented Aug 7, 2022 at 19:06
  • 2
    \$\begingroup\$ @TKirishima It does work on TIO, though it starts falling into the realm of undefined behavior. The program may segfault at any point since s can technically only store 1 element using that declaration. \$\endgroup\$ Commented Aug 7, 2022 at 19:18
  • 7
    \$\begingroup\$ 87 bytes: char*p,s[99];main(i){for(;gets(p=s);--i&&puts(s[1]>87|*p?"Yes":"No"))for(;*p++-p[2];);} \$\endgroup\$ Commented Aug 7, 2022 at 20:52
  • 1
    \$\begingroup\$ @ovs When initialized in the global scope, s[99] should be filled with zeros. Even if p goes past the "end", I believe there would be enough 0s afterwards to terminate the loop. \$\endgroup\$ Commented Aug 8, 2022 at 22:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.