How many countries are in the European Union?

33

3

Tonight, 31 January 2020, Brexit will happen and the United Kingdom will leave the European Union, the first time that the number of EU member states will decrease.

Your job is to take a date and output the number of EU1 members on that date, according to the following table:

| Start      | End        | Number of members 
| 0          | 1957-12-31 | 0
| 1958-01-01 | 1972-12-31 | 6
| 1973-01-01 | 1980-12-31 | 9
| 1981-01-01 | 1985-12-31 | 10
| 1986-01-01 | 1994-12-31 | 12
| 1995-01-01 | 2004-04-30 | 15
| 2004-05-01 | 2006-12-31 | 25
| 2007-01-01 | 2013-06-30 | 27
| 2013-07-01 | 2020-01-31 | 28
| 2020-02-01 | Inf        | 27

Input may take one of the following forms:

  • your language's date format
  • any ordering of integers for year, month and day with any separator (e.g. YYYYMMDD or DD/MM/YYYY)
  • number of days lapsed since some epoch.

This is , so shortest code wins!

1. or EEC before 1993

Robin Ryder

Posted 2020-01-31T10:24:28.070

Reputation: 6 625

1I see the Python answer is using an input as the number of days since 1957-12-31 and the JavaScript answer is taking an input in the format yyyyMM without the dd. Are these both allowed according to the "in any reasonable format"? Both would save bytes in my answer as well. – Kevin Cruijssen – 2020-01-31T12:35:55.087

@KevinCruijssen Number of days since some epoch is OK. yyyyMM is not, as it does not encode a date. – Robin Ryder – 2020-01-31T12:49:20.687

10I feel like in any reasonable format is not objective enough... – Luis Mendo – 2020-01-31T13:19:09.273

1@LuisMendo I think it's OK. It just has to uniquely specify the day. Are you worried there is some possible loophole? – Anush – 2020-01-31T14:31:57.313

3@Anush The problem is how to tell if a format qualifies as "reasonable" or not. For instance, I wouldn't have guessed that Number of days since some epoch (or even months?) does. So a clearer specification is needed – Luis Mendo – 2020-01-31T15:58:32.893

2@LuisMendo I have clarified the input format. – Robin Ryder – 2020-01-31T17:09:40.830

@RobinRyder Thanks. I have retracted my close vote – Luis Mendo – 2020-01-31T18:15:37.887

Note that the new input spec invalidates some answrs. You should notify the authors so they can fix them – Luis Mendo – 2020-01-31T18:16:32.547

@luismendo Thanks. Yes, I plan on notifying them as soon as I get back to a desktop computer. – Robin Ryder – 2020-01-31T18:19:02.303

1Your data is incorrect as the European Union was founded on November 1, 1993 – Rene – 2020-01-31T22:24:00.273

1

Looks like I was off by a year or so :/

– caird coinheringaahing – 2020-01-31T22:53:18.133

@Rene I am also considering the EEC as the EU's predecessor. – Robin Ryder – 2020-01-31T23:01:00.487

1@Robin Ryder, then you should refer to the EEC, not to the EU – Rene – 2020-01-31T23:21:40.407

>

  • pours a 1.18L for the UK *
  • < – Punintended – 2020-01-31T23:27:20.440

    1Should that be -Inf as the starting point for the first line? – ilkkachu – 2020-02-01T15:01:03.987

    @ilkkachu You don't need to be able to handle dates Before the Common Era. – Robin Ryder – 2020-02-01T15:04:59.530

    First, I thought you missed the addition of the GDR to EEC, but then I realisized that the GDR was added to the Federal Republic of Germany, and still counting as one country. So your numbers are still correct. – Julian Egner – 2020-02-02T21:47:02.820

    Answers

    12

    Javascript, 85 83 Bytes

    a=d=>d<0?0:d<180?6:d<276?9:d<336?10:d<444?12:d<556?15:d<588?25:d<666?27:d<745?28:27
    

    It takes an input as a float as the months / fractions of months passed since 1958-01-01
    (0 for 1958-01-01T00:00:00 and a negative number for any previous date)

    (Since number of days from some epoch is allowed, I assume that also a number of months is valid, as well)

    Try it Online


    80 Bytes

    (credits: Arnauld)

    a=d=>d<0?0:d<180?6:d<276?9:d<336?10:d<444?12:d<556?15:d<588?25:27+(d>=666&d<745)
    

    Sad to see you go, UK

    Fabrizio Calderan

    Posted 2020-01-31T10:24:28.070

    Reputation: 470

    Awesome Arnauld! – Fabrizio Calderan – 2020-01-31T15:28:01.457

    3I have clarified what counts as a reasonable input format for dates; number of days since an epoch is allowed but not number of months. Your input format was creative! But it was a loophole, which I have now closed. Your previous version based on number of days would be fine. – Robin Ryder – 2020-01-31T19:31:48.713

    3since JavaScript can't compete with many other golfing languages I wanted to at least be creative. :) – Fabrizio Calderan – 2020-01-31T19:39:25.330

    9

    05AB1E, 29 27 26 25 33 bytes

    ¨12βŽ₅b-‘´`<lp€¸‘Ç.¥@•¿“0p•12в<*O
    

    Try it online!

    Input is in the form [yyyy, mm, dd].

    Grimmy

    Posted 2020-01-31T10:24:28.070

    Reputation: 12 521

    1The most impressive part about this answer is that you thought about using floats as input-format so the compressed integers can all be much shorter. :D – Kevin Cruijssen – 2020-01-31T13:43:34.223

    3@KevinCruijssen I actually took this idea from the JS answer. I added credit to my answer. – Grimmy – 2020-01-31T13:45:56.710

    1@KevinCruijssen yes it was impressive, lol – Fabrizio Calderan – 2020-01-31T13:47:57.833

    2I have clarified what counts as a reasonable input format for dates; number of days since an epoch is allowed but not number of months. – Robin Ryder – 2020-01-31T19:30:51.463

    7

    Python 2, 110 97 bytes

    lambda d:ord('069:<?IKLK'[sum(d>i for i in(0,5479,8401,10227,13514,16922,17897,20270,22676))])-48
    

    Try it online!

    -13 bytes, thanks to Jonathan Allan

    Takes input as number of days since 1957-12-31 (so 1958-01-01 is day 1)


    Python 3, 93 bytes

    lambda d:b'069:<?IKLK'[sum(d>i for i in(0,5479,8401,10227,13514,16922,17897,20270,22676))]-48
    

    Try it online!

    -4 bytes, thanks to mypetlion

    TFeld

    Posted 2020-01-31T10:24:28.070

    Reputation: 19 246

    3

    Save 13 by avoiding the import of bisect

    – Jonathan Allan – 2020-01-31T22:06:36.973

    1Python 3 port saves 4 bytes by replacing ord('069... with b'069... – mypetlion – 2020-01-31T23:45:39.407

    @JonathanAllan Thanks! – TFeld – 2020-02-04T12:37:01.020

    @mypetlion Thanks :) – TFeld – 2020-02-04T12:37:05.533

    6

    05AB1E, 42 36 bytes

    •AÂʒë.š¡ε%ž·7í•ŽL}в.¥›O•=γ1sæΔ•₆вsè<
    

    Input as number of days since 1957-12-31 (so 1957-12-30 is day -1; 1957-12-31 is day 0; 1958-01-01 is day 1; etc.)

    Try it online or verify some more test cases.

    Old 42 bytes answer taking input in the format yyyyMMdd:

    ¨¨•a3|}\§λ’Iœg½þ•ŽOΩв•32Ø•+@O•=γ1sæΔ•₆вsè<
    

    Try it online or verify some more test cases.

    •a3|}\§λ’Iœg½þ•ŽOΩв•32Ø•+ can alternatively be •Me1εä~.=ΔΩ»•Ž5ãв.¥•32Ù•+ for the same byte-count: Try it online or verify some more test cases.

    Explanation:

    •AÂʒë.š¡ε%ž·7í•    # Push compressed integer 813218926689775697373196902446
      ŽL}              # Push compressed integer 5480
         в             # Convert the larger integer to base-5480 as list:
                       #  [5479,2922,1826,3287,3408,975,2373,2406]
          .¥           # Undelta it with leading 0:
                       #  [0,5479,8401,10227,13514,16922,17897,20270,22676]
            ›          # Check for each if it's larger than the (implicit) input-integer
             O         # Take the sum to get the amount of truthy values
    •=γ1sæΔ•           # Push compressed integer 122116126451824
     ₆в                # Convert it to base-36 as list:
                       #  [1,7,10,11,13,16,26,28,29,28]
       sè              # Swap to get the sum, and use it to index into this list
         <             # And decrease it by 1
                       # (since a compressed integer/list cannot contain a leading 0)
                       # (after which the result is output implicitly)
    
    ¨¨                 # Remove the last two digits from the (implicit) input (the "dd")
      •a3|}\§λ’Iœg½þ•  # Push compressed integer 2722385715080006519908031109868
       ŽOΩ             # Push compressed integer 6203
          в            # Convert the larger integer to base-6203 as list:
                       #  [1,1501,2301,2801,3701,4605,4901,5507,6202]
           •32Ø•       # Push compressed integer 195800
                +      # Add it to each value in the list:
                       #  [195801,197301,198101,198601,199501,200405,200701,201307,202002]
                 @     # Check for each if it's larger than or equal to the input minus "dd"
    O•=γ1sæΔ•₆вsè<     # Same as above
    

    See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand how the compression works.

    Kevin Cruijssen

    Posted 2020-01-31T10:24:28.070

    Reputation: 67 575

    6

    Turing Machine Code, 972 1009 bytes

    My input is the date in the format specified in the test cases YYYY-MM-DD.

    0 0 0 * halt
    * 1 _ r €
    € 9 _ r %
    * 2 _ r $
    $ 0 _ r £
    * I 2 r ¢
    % 5 _ r ^
    % 6 6 r c
    % 7 _ r x
    % 8 _ r B
    % 9 _ r i
    % * _ r c
    ^ * 0 r c
    ^ 8 6 r c
    ^ 9 6 r c
    B 0 9 r c
    B 1 1 r r
    B 2 1 r r
    B 3 1 r r
    B 4 1 r r
    B 5 1 r r
    B * 1 r e
    r * 0 r c
    e * 2 r c
    x 0 6 r c
    x 1 6 r c
    x 2 6 r c
    x * 9 r c
    i 0 1 r 
    i 1 1 r 
    i 2 1 r 
    i 3 1 r 
    i 4 1 r 
    i * 1 r t
    t * 5 r c
     * 2 r c
    £ 0 _ r 
    £ 1 _ r ★
    £ 2 _ r 
     0 _ r !
     * 2 r ¢
    ! - _ r ~
    ~ 0 _ r 1
    1 1 2 r ☆
    1 * 2 r ¢
    ★ 0 2 r ¢ 
    ★ 1 2 r ¢
    ★ 2 2 r ¢
    ★ 3 _ r &
    ★ * 2 r ☆
    & - _ r @
    @ 0 _ r 6
    6 0 2 r ¢
    6 1 2 r ¢
    6 2 2 r ¢
    6 3 2 r ¢
    6 4 2 r ¢
    6 5 2 r ¢
    6 6 2 r ¢
    6 * 2 r ☆
    ☆ * 8 r c
     * 5 r c
     1 1 r 
     2 1 r 
     3 1 r 
     4 _ r +
     5 2 r t
     6 2 r t
     * 2 r ¢
    ¢ * 7 r c
    + - _ r ¬
    ¬ 0 _ r 4
    ¬ * 2 r t
    4 0 1 r t
    4 1 1 r t
    4 2 1 r t
    4 3 1 r t
    4 4 1 r t
    4 * 2 r t
    6 _ 6 l c
    c * _ r c
    c _ _ * halt
    
    
     
    

    Try it online!

    Added a few bytes thanks to Grimmy being a bit more thorough in testing my code than I was.

    ouflak

    Posted 2020-01-31T10:24:28.070

    Reputation: 925

    1Seems like it’s all good now! – Grimmy – 2020-01-31T20:32:55.907

    4What's the point of the `` emoji and other multibyte characters? Can they be replaced with characters with lower bytecounts? – caird coinheringaahing – 2020-01-31T22:55:21.863

    @cairdcoinheringaahing, It's the queen's crown. All of the multibyte characters were chosen for the occassion. – ouflak – 2020-02-01T14:11:17.947

    4

    Charcoal, 48 bytes

    I⌕γ§ &)*,/9;<;LΦ⪪”)¶↶⌕βγ⦄J≦σν{:Xδp⁴E⊙≕⍘H⊙βg”⁶‹ιθ
    

    Try it online! Link is to verbose version of code. Takes input as YYYYMMDD. Explanation:

                     ”...”      Compressed string of YYYYMM values
                    ⪪     ⁶     Split into substrings of length 6
                  LΦ       ‹ιθ  Count those that appear before the input
       § &)*,/9;<;              Look the count up in a translation table
    I⌕γ                         Subtract 32 from the ASCII code
    

    Neil

    Posted 2020-01-31T10:24:28.070

    Reputation: 95 035

    4

    Python 2, 158 150 bytes

    i=int(input()[:6]);print((((((((27,28)[202002>i>201306],25)[i<200701],15)[i<200405],12)[i<199501],10)[i<198601],9)[i<198101],6)[i<197301],0)[i<195801]
    

    Try it online!

    Takes input as a string in YYYYMMDD format

    Alternative Python 2 approach without imports. Simply uses nested list indexing to create the equivalent of a big if/elif structure.

    NB: Posted by a British guy who is sorry to see us leave. I'm still all for the Community and working together (whether EU or here).

    ElPedro

    Posted 2020-01-31T10:24:28.070

    Reputation: 5 301

    1Here’s some improvements – Grimmy – 2020-01-31T20:04:54.240

    Hey @Grimmy, that's well smart and different enough for you to post as your own answer. Fine by me. Same priciple, much cooler solution. I'll certainly upvote. – ElPedro – 2020-01-31T21:52:15.483

    3

    Jelly, 38 37 bytes

    “€ɓ⁴5O/ṖṪOṁṪḋg’ḃ⁽×ỵÄŻ>⁸Sị“÷ñıЀ½µ©¡ñ‘
    

    Try it online!

    A monadic link taking the zero-indexed count of days since 1958-01-01 as a integer argument and returning an integer.

    Thanks to @JonathanAllan for saving a byte!

    Nick Kennedy

    Posted 2020-01-31T10:24:28.070

    Reputation: 11 829

    @RobinRyder revised to use days – Nick Kennedy – 2020-01-31T20:07:18.160

    1>⁸TḢị“¡©µ½€Ðıñ÷ñ‘ -> >⁸Sị“÷ñıЀ½µ©¡ñ‘ saves one (maybe with an off by 1 error to fix?) – Jonathan Allan – 2020-01-31T22:23:41.460

    Ah no, looks good, I was using wrong origin date. (d-1,d,d+1) :)

    – Jonathan Allan – 2020-01-31T22:35:35.817

    1

    AWK, 98 bytes

    {m=$1*12+$2-23496}1,$0=m<1?0:m<181?6:m<277?9:m<337?10:m<445?12:m<557?15:m<589?25:27+(m>666&&m<746)
    

    Try it online!

    Input format: YYYY MM DD

    rootbeersoup

    Posted 2020-01-31T10:24:28.070

    Reputation: 111

    1

    JavaScript (ES6), 95 bytes

    Expects a number of days since 1957-12-31.

    n=>[x=0,5479,2922,1826,3287,3408,975,2373,2406].map((d,i)=>x-=(n-=d)>0&&~('52012910'[i]||~1))|x
    

    Try it online!

    This is however a bit longer than @FabrizioCalderan's answer, even if it is fixed to use days instead of months.

    Arnauld

    Posted 2020-01-31T10:24:28.070

    Reputation: 111 334

    1

    x86 (32-bit) assembly, 43 bytes (13 bytes code + 30 bytes data)

    This routine expects input in ax as a signed short giving number of days since 1950-01-01, and returns output in al (clobbering edi along the way).

        .text
        .globl eu_members
    eu_members: 
        mov $.Ltbl-1, %edi
    .Lloop:
        inc %edi
        scas (%edi), %ax
        jg .Lloop
        mov (%edi), %al
        ret
        .section .rodata
    .Ltbl:
        .short 2921
        .byte 0
        .short 8400
        .byte 6
        .short 11322
        .byte 9
        .short 13148
        .byte 10
        .short 16435
        .byte 12
        .short 19843
        .byte 15
        .short 20818
        .byte 25
        .short 23191
        .byte 27
        .short 25597
        .byte 28
        .short 32767
        .byte 27
    

    Exact opcodes of the code part (in a linked context so that the relocation of .Ltbl doesn't confuse things):

    0804930b <eu_members>:
     804930b:       bf 49 a0 04 08          mov    $0x804a049,%edi
     8049310:       47                      inc    %edi
     8049311:       66 af                   scas   %es:(%edi),%ax
     8049313:       7f fb                   jg     8049310 <eu_members+0x5>
     8049315:       8a 07                   mov    (%edi),%al
     8049317:       c3                      ret    
    

    And here's the test harness I used (note that the assembly code is not PIC safe, so on Debian or Ubuntu systems you will need to pass -no-pie to gcc):

    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    #include <string.h>
    
    unsigned char eu_members_wrap(short days_since_1950_01_01) {
        unsigned char res;
        __asm__("call eu_members" : "=a"(res) : "0"(days_since_1950_01_01) : "edi", "cc");
        return res;
    }
    
    int main(int argc, char* argv[]) {
      struct tm tm;
      time_t epoch, req;
      short days_since_epoch;
      memset(&tm, 0, sizeof(tm));
      tm.tm_year = 50;
      tm.tm_mon = 0;
      tm.tm_mday = 1;
      epoch = mktime(&tm);
      memset(&tm, 0, sizeof(tm));
      tm.tm_year = atoi(argv[1]) - 1900;
      tm.tm_mon = atoi(argv[2]) - 1;
      tm.tm_mday = atoi(argv[3]);
      req = mktime(&tm);
      days_since_epoch = (((unsigned int) (req - epoch)) / (24 * 60 * 60));
      /* printf("epoch = %ld, req = %ld\n", epoch, req);
      printf("Raw number of days: %hd\n", days_since_epoch); */
      printf("EU members: %hhu\n", eu_members_wrap(days_since_epoch));
      return 0;
    }
    

    Daniel Schepler

    Posted 2020-01-31T10:24:28.070

    Reputation: 1 001

    Could you use lods (%edi), %al instead of mov (%edi),%al? I am not sure about assembly syntax, but the opcode should work. – anatolyg – 2020-02-02T16:19:17.897

    No, lods can only read from (%esi) – Daniel Schepler – 2020-02-02T20:51:32.050

    -3

    Perl 5, 46 bytes

    ($q,%d)=split;$q--while!exists$d{$q};say$d{$q}
    

    Try it online!

    ...or try like this on some decent command line:

    query=19730101
    data="0 0 19580101 6 19730101 9 19810101 10 19860101 12 19950101 15 20040501 25 20070101 27 20130701 28 20200201 27"
    echo "$query $data" | perl -nE '($q,%d)=split;$q--while!exists$d{$q};say$d{$q}'
    

    Kjetil S.

    Posted 2020-01-31T10:24:28.070

    Reputation: 1 049

    3The data is supposed to be contained in the code, not passed as input. – Arnauld – 2020-02-01T17:48:20.130

    Data is data, code is code, but sometimes code is data and data is code and E=mc² – Kjetil S. – 2020-02-03T14:22:54.743