12
\$\begingroup\$

Doing my history reading and note-taking, I can't help but get tired of writing out all these long dates –– 1784 is six entire pencil lifts! jǝǝz!

As you can see, I –– like most challenge posters on this site –– am lazy when it comes to writing stuff. Thus, I ask you to please help me shorten some dates. Of course, your solution must be as short as possible since my hand is already tired from writing typing out the test cases.

How do I shorten a date?

Well funny you should ask. It's fairly simple:

  1. Take two integers as input in whatever order you want ((smallest, biggest) or (biggest, smallest)).
  2. Take the larger of the two numbers, and take only the part not in the smaller number.
    For example, given 2010, 2017, shorten 2017 to -7 because 201_ is in both at the same digit-places.
  3. Print or return the smaller number, followed by a dash and then the shortened larger number.

For example:

Bonus brownies for you if you figure out these dates' significance :)
1505, 1516 -> 1505-16
1989, 1991 -> 1989-91
1914, 1918 -> 1914-8
1833, 1871 -> 1833-71
1000, 2000 -> 1000-2000
1776, 2017 -> 1776-2017
2016, 2016 -> 2016-

These dates lack significance :(
1234567890, 1234567891 -> 1234567890-1
600, 1600 -> 600-1600
1235, 1424 -> 1235-424
600, 6000 -> 600-6000
\$\endgroup\$
12
  • 4
    \$\begingroup\$ 1914-18 or 1914-8? \$\endgroup\$ Commented Jul 27, 2017 at 22:27
  • 3
    \$\begingroup\$ 600, 6000 -> 600-6000? \$\endgroup\$
    – Qwertiy
    Commented Jul 27, 2017 at 22:27
  • 1
    \$\begingroup\$ @JonathanAllan, yes that’s right. Input is only nonnegative integers \$\endgroup\$
    – Daniel
    Commented Jul 27, 2017 at 23:22
  • 1
    \$\begingroup\$ @Qwertiy, indeed. \$\endgroup\$
    – Daniel
    Commented Jul 27, 2017 at 23:23
  • 2
    \$\begingroup\$ 1914-8 is WWI. Now gimme my brownies! \$\endgroup\$ Commented Jul 28, 2017 at 8:26

12 Answers 12

5
\$\begingroup\$

Jelly,  17  16 bytes

DUµn/TṪṁ@Ṫ,j”-FṚ

A full program taking a list of years from, to and printing the result.

Try it online! or see the test suite.

How?

DUµn/TṪṁ@Ṫ,j”-FṚ - Main link: list of years [from, to]    e.g [1833,1871]
D                - convert to decimals                        [[1,8,3,3],[1,8,7,1]]
 U               - upend (to cater for differing lengths)     [[3,3,8,1],[1,7,8,1]]
  µ              - monadic chain separation, call that V
    /            - reduce V with:
   n             -   not equal?                               [1,1,0,0]
     T           - truthy indices                             [1, 2]
      Ṫ          - tail                                       2
         Ṫ       - tail V (pop from & modify V)               [1,7,8,1]
       ṁ@        - mould (swap @rguments) V like that length  [1,7]
          ,      - pair that with (the modified) V            [[1,7],[[3,3,8,1]]
            ”-   - literal '-' character
           j     - join                                       [1,7,'-',[3,3,8,1]]
              F  - flatten                                    [1,7,'-',3,3,8,1]
               Ṛ - reverse                                    [1,8,3,3,'-',7,1]
                 - implicit print                             1833-71
\$\endgroup\$
1
  • \$\begingroup\$ At first I thought I outgolfed this...then damn [600, 6000] appeared. And it seems this has been undervoted. \$\endgroup\$ Commented Jul 28, 2017 at 8:59
3
\$\begingroup\$

Javascript ES6, 59 57 chars

(x,y)=>(x+'-'+y).replace(x*10>y?/^((.*).*-)\2/:/()/,"$1")

Test:

f=(x,y)=>(x+'-'+y).replace(x*10>y?/^((.*).*-)\2/:/()/,"$1")

console.log(`1505, 1516 -> 1505-16
1989, 1991 -> 1989-91
1914, 1918 -> 1914-8
1833, 1871 -> 1833-71
1000, 2000 -> 1000-2000
1776, 2017 -> 1776-2017
2016, 2016 -> 2016-
1234567890, 1234567891 -> 1234567890-1
600, 1600 -> 600-1600
1235, 1424 -> 1235-424`.split`
`.map(t => t.match(/(\d+), (\d+) -> (.*)/)).every(([m,x,y,key]) => f(x,y)===key || console.log(x,y,key,f(x,y))))
console.log(f(600,6000))

\$\endgroup\$
3
  • \$\begingroup\$ Just try (x+'-'+y) ? \$\endgroup\$
    – tsh
    Commented Jul 28, 2017 at 5:28
  • \$\begingroup\$ f(180, 1600) -> ? \$\endgroup\$
    – tsh
    Commented Jul 28, 2017 at 5:32
  • 1
    \$\begingroup\$ Use currying (x=>y=>) to save a byte. \$\endgroup\$ Commented Jul 28, 2017 at 8:46
1
\$\begingroup\$

05AB1E, 16 bytes

`R¹íζ€Ë1Üg£R‚'-ý

Try it online!

Uses Jonathan Allan's algorithm.

\$\endgroup\$
1
\$\begingroup\$

Dyalog APL, 29 bytes

{⍺,'-',x/⍨⌈\~((-⍴x)↑⍕⍺)=x←⍕⍵}

Try it online!

How?

⍺,'-' - the first year + , -

    =x←⍕⍵ - compare the second year formatted

    ((-⍴x)↑⍕⍺) - to the first year padded with spaces from left

    ⌈\~ - negate the result and mark all 1s after the first

x/⍨ - take the second year in all marked position

\$\endgroup\$
1
\$\begingroup\$

Retina, 34 bytes

(.*)((.)*),\1((?<-3>.)*)\b
$1$2-$4

Try it online! Link includes test cases. The balancing group and the word boundary ensure that both numbers are the same length before the prefix is matched. If not, then the word boundary matches at the start of the second year, so all that happens is that the comma changes to a dash.

\$\endgroup\$
1
\$\begingroup\$

Python 2, 102 bytes

lambda s,n:`s`+'-'+[[`n`[i:]for i in range(len(`s`)+1)if `n`[:i]==`s`[:i]][-1],`n`][len(`n`)>len(`s`)]

Try it online!

I feel like there has to be a better way to do this since it seems really verbose. Extreme abuse of the `` evaluation of variables for this to work since we can't take strings as input.

\$\endgroup\$
2
  • \$\begingroup\$ a=100,b=199 returns "100-199" instead of "100-99". \$\endgroup\$
    – Chas Brown
    Commented Jul 29, 2017 at 1:10
  • \$\begingroup\$ @ChasBrown Dang, you're right. I rolled back my code to the previous iteration, which takes care of this case. \$\endgroup\$ Commented Jul 29, 2017 at 11:59
1
\$\begingroup\$

Haskell, 92 bytes

f=q.map show;q[a,b]=a++"-"++if(1<$a)<(1<$b)then b else snd<$>(snd$span(uncurry(==))$zip a b)

Takes input as a list of two integers [earlier date, later date].

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Very nice! Since it's not recursive you don't need the f=, then you can do a bit of rearranging to get down to 88. \$\endgroup\$ Commented Aug 22, 2022 at 9:29
0
\$\begingroup\$

Python 2, 127 bytes

I am still new to this, so I don't know if it is okay to place another answer in the same language. Since I can't comment on other peoples posts yet I take my chances here.

  • Is it allowed to change the input from Integer to String? Cause that would save me around 10 bytes.
  • Arnlod Parmers answer has a mistake on 1989, 1991. (during the time I am posting this). Thank you tho for the `` evaluation trick tho (it saved me a byte)!
def f(s,b):
 s=`s`+'-'
 if len(`b`)>=len(s):return s+`b`
 for i in range(len(`b`)):
    if s[i]!=`b`[i]:return s+`b`[i:]
 return s

Try it online!

What I do is, I compare each single digit from both times and if the bigger one varies I print the smaller number plus the rest of the bigger one.

If someone could help me golf out the third line I would save like 30+ bytes. I only implemented it to handle the case of 600,6000 where the digits are equal but not the same length.

\$\endgroup\$
1
  • \$\begingroup\$ Yeah, it's ok to answer the same question in multiple languages, and you are allowed to take the input as String. \$\endgroup\$
    – geokavel
    Commented Jul 28, 2017 at 16:44
0
\$\begingroup\$

Haskell, 143 bytes

g x y=h(show x)(show y)
h x y=x++"-"++if length x<length y then y else foldl(\a(c,d)->if a==[]then if c==d then[]else[d]else a++[d])[](zip x y)

Try it online!

smallest biggest input (integers).

if length x<length y then y means that if x has less digits than y then the common part is void. Else, we store the digits of y from the first different digit.

\$\endgroup\$
0
\$\begingroup\$

Python 2, 89 88 bytes

lambda a,b:`a`+'-'+`b`[map(lambda c,d:(len(`a`)==len(`b`))*(c==d),`a`,`b*10`).index(0):]

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Common Lisp, 120 bytes

(lambda(s b &aux(d(#1=format()"~a"b)))(#1#()"~a-~a"s(if(<=(* s 10)b)b(subseq d(or(mismatch d(#1#()"~a"s))(length d))))))

Try it online!

Smallest, Biggest.

Ungolfed:

(defun f(s b &aux (d (format () "~a" b)))   ; s and b parameters, d string from s
  (format () "~a-~a" s                     ; print first number, then -, then abbreviation
      (if (<= (* s 10) b)                  ; if b is too large do not abbreviate
          b
          (subseq d (or (mismatch d (format () "~a" s)) ; else find first mismatch
                        (length d))))))    ; then extract the last part from mismatch
                                           ; or nothing if they are equal
\$\endgroup\$
0
\$\begingroup\$

C++, 285 271 bytes

-14 bytes thanks to Zacharý

#include<iostream>
#include<string>
#define S s.size()
#define R r.size()
using namespace std;void h(int a,int b){auto r=to_string(a),s=to_string(b);if(R>S)s=string(R-S,' ')+s;if(S>R)r=string(S-R,' ')+r;int i=0;for(;i<R;++i)if(r[i]!=s[i])break;cout<<a<<'-'<<s.substr(i);}

Code for testing :

std::vector<std::pair<int, int>> test = {
    {1505,1516},
    {1989,1991}, //End of the cold war
    {1914,1918}, //First world war start and end
    {1833,1871},
    {1000,2000}, //2000 = Y2K bug, 1000 is... well... Y1K bug ? :)
    {1776,2017}, //US constitution signed the 4th july, French elections & year of the C++ 17 standard
    {2016,2016}, //US elections
    {1234567890,1234567891},
    {600,1600},
    {1235,1424},
    {600,6000}
};

for (auto&a : test) {
    h(a.first, a.second);
    std::cout << '\n';
}
\$\endgroup\$
1
  • \$\begingroup\$ You can save a few bytes by using namespace std; and removing the T macro. \$\endgroup\$
    – Adalynn
    Commented Jul 30, 2017 at 20:48

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.