Hi! I’ve recently started learning C and I’ve been getting stuck on the basic tasks cuz I keep overcomplicating them T-T Could anyone please help me with this specific task?

Problem Statement

You have a digit sequence S of length 4. You are wondering which of the following formats S is in:

  • YYMM format: the last two digits of the year and the two-digit representation of the month (example: 01 for January), concatenated in this order
  • MMYY format: the two-digit representation of the month and the last two digits of the year, concatenated in this order

If S is valid in only YYMM format, print YYMM; if S is valid in only MMYY format, print MMYY; if S is valid in both formats, print AMBIGUOUS; if S is valid in neither format, print NA.

Constraints
- S is a digit sequence of length 4.

Sample Input 1
1905

Sample Output 1
YYMM
May XX19 is a valid date, but 19 is not valid as a month. Thus, this string is only valid in YYMM format.

Sample Input 2
0112

Sample 2
AMBIGUOUS
Both December XX01 and January XX12 are valid dates. Thus, this string is valid in both formats.

Sample Input 3
1700

Sample Output 3
NA
Neither 0 nor 17 is valid as a month. Thus, this string is valid in neither format.

The code I wrote for this is:

#include <stdio.h>

int main(){
    int S;
    scanf("%d", &S);
    int p1 = S/100;
    int p2 = S%100;
    if (p1!=0 && p1<=12){
        if(p2!=0 && p2<=12){
            printf("AMBIGUOUS");
        }
        else if (p2>=13){
            printf("MMYY");
        }
        else{
            printf("NA");
        }
    }
    else if (p1>=13){
        
        if(p2!=0 && p2<=12){
            printf("YYMM");
        }
        else {
            printf("NA");
        }
    }
   return 0;
}

It passed the 7 checks in the system, but failed on the 8th and I have no idea what kind of values are on the 8th check… Thanks to anyone for reading this far!

  • 6nk06@sh.itjust.works
    link
    fedilink
    arrow-up
    10
    ·
    edit-2
    13 days ago

    No time to check but:

    • scanf("%4d", &S) or something
    • you have if, else if, but no simple else in the end
    • add \n to printf

    Last but not least: move the code after scanf to its own function that takes 1 number XXXX or 2 numbers (XX and YY), and call it in a loop for (int i = 0; i < 9999; ++i) and print the results like: “p1, p2, result”, that way you’ll quickly check which value is invalid or not.

    • yris@lemmy.zipOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      13 days ago

      Thank you for your reply!! I’ll look into it! Although I don’t think I’ll be able to make it a function(I’ve been procrastinating studying that topic🫠)

  • ludrol
    link
    fedilink
    arrow-up
    5
    ·
    13 days ago

    If input is 0 then the program prints nothing instead of NA

    • yris@lemmy.zipOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      13 days ago

      The site that accepts & checks this code is programmed to only input 4 digit inputs so i didn’t account for any other options

      • ludrol
        link
        fedilink
        arrow-up
        2
        ·
        12 days ago

        Input 0000 and 0 are the same in the flow of your program.

  • BB_C
    link
    fedilink
    arrow-up
    3
    arrow-down
    1
    ·
    13 days ago

    Maybe something like this

    #include <stdio.h>
    
    // reads next 4 chars. doesn't check what's beyond that.
    int get_pair() {
      int h = getchar() - 48;
      int l = getchar() - 48;
    
      return h * 10 + l;
    }
    
    int main(){
      int p0 = get_pair();
      int p1 = get_pair();
      if (p0 < 0 || p1 < 0 || p0 > 100 || p1 > 100) {
       // not 4 digi seq, return with failure if that's a requirement 
      }
    
      if ((p0 == 0 || p0 > 12) && (p1 >= 1 && p1 <= 12)) {
        printf("YYMM");
      } else if ((p1 == 0 || p1 > 12) && (p0 >= 1 && p0 <= 12)) {
        printf("MMYY");
      } else if ((p0 >= 1 && p0 <= 12) && (p1 >= 1 && p1 <= 12)) {
        printf("AMBIGUOUS");
      } else {
        printf("NA");
      }
      return 0;
    }
    

    or if you want to optimize

    #include <stdio.h>
    #include <stdint.h>
    
    // reads next 4 chars. doesn't check what's beyond that.
    int get_pair() {
      int h = getchar() - 48;
      int l = getchar() - 48;
    
      return h * 10 + l;
    }
    
    uint8_t props (int p) {
      if (p >= 1 && p <= 12) {
        return 0b10;
      } else if (p < 0 || p >= 100) {
        return 0b11;
      } else {
        return 0b00;
      }
    }
    
    int main(){
      int p0 = get_pair();
      int p1 = get_pair();
    
      switch (props(p0) | (props(p1) << 2)) {
        case 0b1010: printf("AMBIGUOUS"); break;
        case 0b1000: printf("YYMM"); break;
        case 0b0010: printf("MMYY"); break;
        default: printf("NA");
      }
      return 0;
    }
    
    • yris@lemmy.zipOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      2 days ago

      Yeah, it worked, thanks a lot!! Could you explain what deducing 48 out of h and l does? I don’t want to just copy and forget abt this(no pressure, you already helped a lot!!!)

      • BB_C
        link
        fedilink
        arrow-up
        1
        ·
        edit-2
        2 days ago

        '0'..'9' (characters in ASCII) are (0+48)..(9+48) when read as integer values.

        For readability you can do:

          unsigned char zero = '0';
          int h = getchar() - zero;
          int l = getchar() - zero;
        

        And as I mentioned in another comment, if this was serious code, you would check that both h and l are between 0 and 9.

        Note that one of the stupid quirks about C is that char is not guaranteed to be unsigned in certain implementations/architectures. So it’s better to be explicit about expecting unsigned values. This is also why man 3 getchar states:

        fgetc() reads the next character from stream and returns it as an unsigned char cast to an int, or EOF on end of file or error.

        getchar() is equivalent to fgetc(stdin).

    • yris@lemmy.zipOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      13 days ago

      Thank you so much for your time! Holy shit you went deep there, even optimized it😭 I’m 4ever grateful, gotta go try it, be back with results!

    • entwine
      link
      fedilink
      arrow-up
      1
      ·
      12 days ago

      This is unnecessarily complicated, and I don’t see how your second version is supposed to be more optimal? You’re just adding pointless indirection by encoding the branching logic as an int, and then branching again in a switch statement.

      • BB_C
        link
        fedilink
        arrow-up
        1
        arrow-down
        1
        ·
        12 days ago

        This is unnecessarily complicated

        really!

        and I don’t see how your second version is supposed to be more optimal?

        It was a half-joke. But since you asked, It doesn’t do any duplicate range checks.

        But it’s not like any of this is going to be measurable.

        Things you should/could have complained about:

        • [semantics] not checking if h and l are in the [0, 9] range before taking the result of h*10 + l.
        • [logical consistency] not using a set bet for [0, 100] and a set bit for [1, 12], and having both bits set for the latter.
        • [cosmetic/visual] not having the props bits for p0 on the left in the switch.

        And as a final note, you might want to check what kind of code compilers actually generate (with -O2/-O3 of course). Because your complaints don’t point to someone who knows.

  • entwine
    link
    fedilink
    arrow-up
    2
    ·
    12 days ago

    This would be easier to understand if you defined a function like:

    char IsMonth(int value){
        return value > 0 && value <= 12;
    }
    

    Then try to rewrite your program using that inside of the if statements. For example

    if(IsMonth(p1)){
        ...
    }
    

    If you do that, I’m pretty sure you’ll find the problem. As a hint, notice that IsMonth is a boolean value, since a number can only either be a month (true) or not a month (false). I haven’t debugged it, but I can tell there’s a problem just by the number of printf statements you currently have.

  • calliope@retrolemmy.com
    link
    fedilink
    arrow-up
    2
    ·
    13 days ago

    What happens in your program when scanf stores -1 as the value, like if it hits EOL before finding matching input?

    Maybe you covered this and I missed it.

    • yris@lemmy.zipOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      13 days ago

      The site where I submit my answers only inputs four digit positive numbers so idk either ¯_(ツ)_/¯

  • Daedskin@lemmy.zip
    link
    fedilink
    arrow-up
    1
    ·
    12 days ago

    If the input is anything of the form 00XX, then p1 == 0. This will fail for p1 != 0 as well as p1 >= 13, meaning neither of the top-level ifs will trigger.