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\$
  • 4
    \$\begingroup\$ 1914-18 or 1914-8? \$\endgroup\$ – Anders Kaseorg Jul 27 '17 at 22:27
  • 3
    \$\begingroup\$ 600, 6000 -> 600-6000? \$\endgroup\$ – Qwertiy Jul 27 '17 at 22:27
  • 1
    \$\begingroup\$ @JonathanAllan, yes that’s right. Input is only nonnegative integers \$\endgroup\$ – Daniel Jul 27 '17 at 23:22
  • 1
    \$\begingroup\$ @Qwertiy, indeed. \$\endgroup\$ – Daniel Jul 27 '17 at 23:23
  • 2
    \$\begingroup\$ 1914-8 is WWI. Now gimme my brownies! \$\endgroup\$ – Erik the Outgolfer Jul 28 '17 at 8:26

11 Answers 11

0
\$\begingroup\$

05AB1E, 16 bytes

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

Try it online!

Uses Jonathan Allan's algorithm.

\$\endgroup\$
4
\$\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\$
  • \$\begingroup\$ At first I thought I outgolfed this...then damn [600, 6000] appeared. And it seems this has been undervoted. \$\endgroup\$ – Erik the Outgolfer Jul 28 '17 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\$
  • \$\begingroup\$ Just try (x+'-'+y) ? \$\endgroup\$ – tsh Jul 28 '17 at 5:28
  • \$\begingroup\$ f(180, 1600) -> ? \$\endgroup\$ – tsh Jul 28 '17 at 5:32
  • 1
    \$\begingroup\$ Use currying (x=>y=>) to save a byte. \$\endgroup\$ – TheLethalCoder Jul 28 '17 at 8:46
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\$
  • \$\begingroup\$ a=100,b=199 returns "100-199" instead of "100-99". \$\endgroup\$ – Chas Brown Jul 29 '17 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\$ – Arnold Palmer Jul 29 '17 at 11:59
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\$
  • \$\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 Jul 28 '17 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\$
  • \$\begingroup\$ You can save a few bytes by using namespace std; and removing the T macro. \$\endgroup\$ – Zacharý Jul 30 '17 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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