13
\$\begingroup\$

Goal: This goal to take a string and output how many contributions should be made on which days in order to display a message.

enter image description here

Specification

  • Input
    • Support letters plus space (i.e. [A-Za-z ] )
    • Space is a blank 3X7
    • The letters are defined in this 5x7 DOT Matrix font provided below
    • The size of each letter is the minimum bounding rectangle (e.g. l = 3x7, e = 5x5)
  • Coloring
    • There are 5 colors C0, C1, C2, C3, C4
    • CX requires Y contributions with 3X <= y < 3(X+1)
    • Letters should alternate between C1 and C2
    • Spaces have no color
    • Each letter size should overlap exactly 1 column with adjacent letters
    • If a cell has more than 1 color then use C3
  • Dot Matrix
    • The dot matrix is Github's contribution history graph
    • If today is Monday, May 1st, 2017:
 4-30    5-07    5-15
[5-01]   5-08    5-16
 5-02    5-09     .
 5-03    5-10     .
 5-04    5-12     .
 5-05    5-13    
 5-06    5-14    
  • Output
    • Flexible on how this is given
    • (x, y) pairs
    • x is a date greater than or equal to the current date
    • y is the number of contributions to be made on the date, x
    • Should be in chronological order (so I can fill in my calendar)
    • If for each date, x, the given y contributions are made, the input message should show up on the Github graph (with correct coloring)
    • The first date should the earliest possible
  • Scoring
    • Shortest program/function in bytes wins

Alphabet

Created by sylvan.black under CC

enter image description here enter image description here


Test Cases

For these test cases, assume the current date is May 25th, 2017.

Input -> Output
-----    ------
l        5-28-17, 3
         6-3-17, 3
         6-4-17, 3
         6-5-17, 3
         6-6-17, 3
         6-7-17, 3
         6-8-17, 3
         6-9-17, 3
         6-10-17, 3
         6-17-17, 3

He       5-28-17, 3
         5-29-17, 3
         5-30-17, 3
         5-31-17, 3
         6-1-17, 3
         6-2-17, 3
         6-3-17, 3
         6-7-17, 3
         6-14-17, 3
         6-21-17, 3
         6-25-17, 3
         6-26-17, 3
         6-27-17, 3
         6-28-17, 9
         6-29-17, 9
         6-30-17, 9
         7-1-17, 3
         7-4-17, 6
         7-6-17, 6
         7-8-17, 6
         7-11-17, 6
         7-13-17, 6
         7-15-17, 6
         7-18-17, 6
         7-20-17, 6
         7-22-17, 6
         7-26-17, 6
         7-27-17, 6

o W      5-31-17, 3
         6-1-17, 3
         6-2-17, 3
         6-6-17, 3
         6-10-17, 3
         6-13-17, 3
         6-17-17, 3
         6-20-17, 3
         6-24-17, 3
         6-28-17, 3
         6-29-17, 3
         6-30-17, 3
         7-9-17, 6
         7-10-17, 6
         7-11-17, 6
         7-12-17, 6
         7-13-17, 6
         7-14-17, 6
         7-22-17, 6
         7-26-17, 6
         7-27-17, 6
         7-28-17, 6
         8-5-17, 6
         8-6-17, 6
         8-7-17, 6
         8-8-17, 6
         8-9-17, 6
         8-10-17, 6
         8-11-17, 6
\$\endgroup\$
  • \$\begingroup\$ Is C4 ever used? \$\endgroup\$ – FryAmTheEggman May 30 '17 at 15:01
  • \$\begingroup\$ @FryAmTheEggman It is not, but I included it to avoid confusion because Github displays 5 colors in the legend. \$\endgroup\$ – NonlinearFruit May 30 '17 at 15:04
  • \$\begingroup\$ How strict/loose are you on date output format? \$\endgroup\$ – Stephen May 30 '17 at 15:33
  • 1
    \$\begingroup\$ @StephenS It is flexible, as long as it is human readable (e.g. May 20th, 2017: 3, (3,"20/5/17") ) \$\endgroup\$ – NonlinearFruit May 30 '17 at 15:36
  • \$\begingroup\$ Where did you find that contribution table? \$\endgroup\$ – Erik the Outgolfer May 30 '17 at 16:44
11
+100
\$\begingroup\$

JavaScript (ES6), 743 bytes

s=>(n=y=>d.setDate(d.getDate()+y),d=new Date,(h=d.getDay())&&n(7-h),r={},i=0,[...s].map(c=>{c<"!"?n(14):([...parseInt("jn4x733nx8gjw6nhricv6nx8dpz2vilui81vikl7b4nhridnzvgc1svznx8dji8g16fkg0vgc6341vg38oe9vh669ofvgm1dvjnhricvyvikl7aonhrjrjxvikmm29m0rqqp2nqmi6o0vbnf6dav2t14e4vbnjqpqs0g34o3tlqqwdso43oixtg1uyt8vvgddxn2hizrn2ahizrmdbhj4suq4gtytq8wgshvtzyvgc4mq7gzhwhz4g15ymf4vg72q9snx7r2f4jmffjm7jm5gavjhizrn2mjmkh3wogsgmianjm5gavcgwxpc3mhvni2kijhgqujjj8mcsgsjhgslnihw2cx75iqyv1cuhwdrh5d".substr((c.charCodeAt()-(c>"`"?71:65))*7,7),36).toString(2).slice(1).replace(/(0{7})+$/,"")].map(b=>(+b&&(r[+d]=r[+d]?9:i%2?6:3),n(1))),i++,n(-7))}),Object.keys(r).map(k=>[k,r[k]]).sort((i,j)=>i[0]-j[0]>0?1:-1).map(i=>[(new Date(+i[0])+"").slice(4,15),i[1]]))

Output is an array of 2-item arrays in the form [dateString, contribs]. The snippet below shows how that can be formatted into being more readable.

Un-Golfed

s=>(
    n=y=>d.setDate(d.getDate()+y),
    d=new Date,
    (h=d.getDay()) && n(7-h),
    r={},
    i=0,
    [...s].map(c=>{
        c<"!" ? n(14) : (
            [...parseInt("<...>".substr((c.charCodeAt()-(c>"`"?71:65))*7,7),36).toString(2).slice(1).replace(/(0{7})+$/,"")].map(b=>(
                +b && (r[+d] = r[+d] ? 9 : i%2?6:3),
                n(1)
            )),
            i++,
            n(-7)
        )
    }),
    Object.keys(r)
        .map(k=>[k,r[k]])
        .sort((i,j)=>i[0]-j[0] > 0 ? 1 : -1)
        .map(i => [ (new Date(+i[0])+"").slice(4,15), i[1] ])
)

Where <...> represents the 364-byte string of characters that I created to encode each letter's dot matrix form.

Explanation

The encoded string:

jn4x733nx8gjw6nhricv6nx8dpz2vilui81vikl7b4nhridnzvgc1svznx8dji8g16fkg0vgc6341vg38oe9vh669ofvgm1dvjnhricvyvikl7aonhrjrjxvikmm29m0rqqp2nqmi6o0vbnf6dav2t14e4vbnjqpqs0g34o3tlqqwdso43oixtg1uyt8vvgddxn2hizrn2ahizrmdbhj4suq4gtytq8wgshvtzyvgc4mq7gzhwhz4g15ymf4vg72q9snx7r2f4jmffjm7jm5gavjhizrn2mjmkh3wogsgmianjm5gavcgwxpc3mhvni2kijhgqujjj8mcsgsjhgslnihw2cx75iqyv1cuhwdrh5d

Each 7 characters is a base-36 encoded binary number that contains the mapping for the character at that index. The binary form always has a leading 1 in order to preserve the leading 0s. For example, an uppercase T maps to nqmi6o0, which converts to 1100 00001000 00011111 11100000 01000000. Skipping the leading 1, each bit is one day. Most numbers have 5 columns/weeks, so the numbers with less than 5 columns have one or two sets of 7 trailing zeros that are later removed before parsing (.replace(/(0{7})+$/,"")). This keeps all encoded strings the same length, removing the need for delimiters.

There's probably still more ways to improve upon this, especially with compressing the letter mappings further, so feel free to share any ideas.

Binary format of the letter mappings (JS syntax, prefixed with 0b), can be found here.

Basic Snippet

f=
s=>(n=y=>d.setDate(d.getDate()+y),d=new Date,(h=d.getDay())&&n(7-h),r={},i=0,[...s].map(c=>{c<"!"?n(14):([...parseInt("jn4x733nx8gjw6nhricv6nx8dpz2vilui81vikl7b4nhridnzvgc1svznx8dji8g16fkg0vgc6341vg38oe9vh669ofvgm1dvjnhricvyvikl7aonhrjrjxvikmm29m0rqqp2nqmi6o0vbnf6dav2t14e4vbnjqpqs0g34o3tlqqwdso43oixtg1uyt8vvgddxn2hizrn2ahizrmdbhj4suq4gtytq8wgshvtzyvgc4mq7gzhwhz4g15ymf4vg72q9snx7r2f4jmffjm7jm5gavjhizrn2mjmkh3wogsgmianjm5gavcgwxpc3mhvni2kijhgqujjj8mcsgsjhgslnihw2cx75iqyv1cuhwdrh5d".substr((c.charCodeAt()-(c>"`"?71:65))*7,7),36).toString(2).slice(1).replace(/(0{7})+$/,"")].map(b=>(+b&&(r[+d]=r[+d]?9:i%2?6:3),n(1))),i++,n(-7))}),Object.keys(r).map(k=>[k,r[k]]).sort((i,j)=>i[0]-j[0]>0?1:-1).map(i=>[(new Date(+i[0])+"").slice(4,15),i[1]]))

I.value="Hello World";
(I.oninput=_=>O.innerHTML = f(I.value).map(e=>e.join(": ")).join("\n"))();
<input id="I">
<pre id="O">

Interactive example

Using the library cal-heatmap, I created an interactive heatmap of the dates that are output. This was used to test everything while working, and it just looks plain neat.

\$\endgroup\$
  • 1
    \$\begingroup\$ The interactive example is really awesome. Nice job! \$\endgroup\$ – NonlinearFruit Jun 8 '17 at 2:57
  • 1
    \$\begingroup\$ Oh god, someone actually did this! Nice! \$\endgroup\$ – Magic Octopus Urn Jun 8 '17 at 15:06
  • \$\begingroup\$ Thanks guys! This was a really cool challenge, I wish more people would come attempt it. I've edited my answer to include the dot matrix letters in binary so that others can use the same idea. \$\endgroup\$ – Justin Mariner Jun 10 '17 at 2:05
  • 1
    \$\begingroup\$ @JustinMariner I popped this onto my profile, hope you don't mind. Nice answer, glad someone completed this challenge :) \$\endgroup\$ – Stephen Jun 10 '17 at 2:14
  • \$\begingroup\$ @StephenS Nice, glad you liked it! \$\endgroup\$ – Justin Mariner Jun 10 '17 at 2:20

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.