Print "Hey Jude" from The Beatles

28

4

Your task is to write a program which prints following four verses extracted from the lyrics from The Beatles' song "Hey Jude" (© Sony/ATV Music Publishing LLC):

Hey Jude, don't make it bad\n
Take a sad song and make it better\n
Remember to let her into your heart\n
Then you can start to make it better\n
\n
Hey Jude, don't be afraid\n
You were made to go out and get her\n
The minute you let her under your skin\n
Then you begin to make it better\n
\n
Hey Jude, don't let me down\n
You have found her, now go and get her\n
Remember to let her into your heart\n
Then you can start to make it better\n
\n
Hey Jude, don't make it bad\n
Take a sad song and make it better\n
Remember to let her under your skin\n
Then you'll begin to make it\n
\n

BUT

The only input you are allowed to use to construct these four verses is this list of tokens:

"Hey Jude, don't"
" make it bad"
" be afraid"
" let me down"
"Take a sad song and make it better"
"You"
" were made to go out"
" and get her"
" have found her, now go"
"Remember to"
"The minute you"
" let her"
" into your heart"
" under your skin"
"Then"
" you"
" can start"
"'ll"
" begin"
" to make it"
" better"

Note that some tokens have a space preceded and that enclosing quotes are not part of the tokens. You are free to use any format for the list and to rearrange the order of the tokens.

Your generated output has to exactly match the above four verses. Note that\n is used for newlines and an extra newline is added after each verse. You can use this file (MD5: 4551829c84a370fc5e6eb1d5c854cbec) to check your output against.

You can use following railroad diagram to understand the structure of the verses (each element represents a token): enter image description here

Shortest code in bytes wins. Happy golfing.

arminb

Posted 2018-02-19T15:55:21.677

Reputation: 783

Just to make this clear: my understanding is that the tokens are passed to the program/function and do not contribute to the byte count. Is that correct? – Arnauld – 2018-02-19T16:01:59.777

@Arnauld Yes, that's correct. – arminb – 2018-02-19T16:02:34.083

47The part that goes Nah nah nah nah nah nah, nah nah nah, would have easier to compress. ^^ – Arnauld – 2018-02-19T16:14:54.230

1Given that the input is any ordering of a fixed set I think tagging as kolmogorov-complexity makes sense. I've added it, if people disagree then just remove it :) – Jonathan Allan – 2018-02-19T16:17:36.063

3

@Arnauld Related :P

– James – 2018-02-19T16:20:39.787

10

@Arnauld obligatory XKCD https://xkcd.com/851_make_it_better/

– Nathaniel – 2018-02-20T00:30:06.863

3It must be hard to sing all those backslashes at the end of every line. – Tamás Sengel – 2018-02-20T10:36:46.900

@arminb what did you use to make that diagram? So pretty.... – bonh – 2018-02-20T14:31:35.490

2

@bonh railroad-diagrams

– arminb – 2018-02-20T15:03:03.507

2Ruby: loop { puts 'na' } – AJFaraday – 2018-02-20T16:12:56.113

Possible duplicate of We're no strangers to code golf, you know the rules, and so do I

– FantaC – 2018-03-05T23:50:54.433

You confusingly put two newlines at the end of each line of the song. I recommend you edit one out. – msh210 – 2018-03-06T21:45:11.817

Answers

9

Jelly, 42 bytes

;⁷“Ṙç€ṘḋḷŒø|Ṁ2kḤ⁽⁼SƁẒVṿẎj]ð⁵ṀƒƤ)÷Ƒ¦Ẋ½Iɠ⁻’ṃ

Try it online!

Hardcoding version.

Input:

["Hey Jude, don't", ' make it bad', 'Take a sad song and make it better', 'Remember to', ' let her', ' into your heart', 'Then', ' you', ' can start', ' to make it', ' better', ' be afraid', 'You', ' were made to go out', ' and get her', 'The minute you', ' under your skin', ' begin', ' let me down', ' have found her, now go', "'ll"]

Erik the Outgolfer

Posted 2018-02-19T15:55:21.677

Reputation: 38 134

17

JavaScript (ES6), 108 bytes

a=>`01
4
9bc
efgjk

02
567
abd
efijk

03
587
9bc
efgjk

01
4
9bd
efhij

`.replace(/./g,n=>a[parseInt(n,36)])

Try it online!


Alternate version, 114 bytes

A slightly better compression, but sadly ruined by the larger decompression code.

a=>`835fc3cbbd3
84db3db4bbdb3
85cd1cc3cbbd3
835fc4bbcb3

`.replace(/./g,n=>a[n='0x'+n,i=n%8&&n%8-2+i]+[`
`[n>>3]])

Try it online!

Arnauld

Posted 2018-02-19T15:55:21.677

Reputation: 111 334

I did not know that the m flag is not required for multi-line template literals. Interesting. – Grant Miller – 2018-02-27T00:56:06.947

7

Ruby + -p, 177 136 120 118 115 109 bytes (full program)

$_="abvevjlmvopqtuvvacvfghvklnvopstuvvadvfihvjlmvopqtuvvabvevjlnvoprstv".gsub(/./){|c|(eval$_)[c.ord-97]||$/}

Try it online!

-41 bytes: Switch from using variables to using characters as array indexes

-16 bytes: Switch to a more convenient input format

-1 byte: No space needed between puts and "abv...

-1 byte: Use $/ global instead of ?\n literal

-3 bytes: Use gsub(/./) instead of .chars.map

-6 bytes: Call with -p and make use of $_. Thanks Pavel!

Each character in the magic string represents an index into the input array. I need the variable z so that I only read from STDIN once.

I could save some cost from IO by writing a lambda accepting an array and returning a string. This requires an extra v at the end, because it's not getting a free newline from -p.

Ruby, 162 110 108 105 bytes (function)

->z{"abvevjlmvopqtuvvacvfghvklnvopstuvvadvfihvjlmvopqtuvvabvevjlnvoprstvv".gsub(/./){|c|z[c.ord-97]||$/}}

Try it online!

benj2240

Posted 2018-02-19T15:55:21.677

Reputation: 801

I haven't been able to find a way to use String#unpack to be shorter than .chars with .ord-97, but there might be one. – benj2240 – 2018-02-19T22:01:26.783

Neat, thanks! Today I learned about -p and $_ – benj2240 – 2018-02-20T05:22:32.290

Forgive my ignorance, but how would I run this from the command-line or IRB? – John Topley – 2018-02-21T08:47:17.463

1

@JohnTopley If you want to use IRB, you could copy-paste these three lines one by one. To use the full program from the command line, start here

– benj2240 – 2018-03-02T18:49:32.227

4

Java 8, 241 233 141 140 138 bytes

a->{a.add("\n");"01E4E9;<E>?@CDEE02E567E:;=E>?@CDEE03E587E91<E>?@CDEE01E4E91=E>?ABCEE".chars().forEach(i->System.out.print(a.get(i-48)));}

Explanation:

Try it online.

a->{                  // Method with ArrayList<String> parameter and no return-type
 a.add("\n");         //  Add a new-line as last item (index 21) to the input-List
 "01E4E9;<E>?@CDEE02E567E:;=E>?@CDEE03E587E91<E>?@CDEE01E4E91=E>?ABCEE".chars().forEach(i->
                      //  Loop over the bytes of this String above
   System.out.print(  //   Print:
     a.get(i-48)));}  //    The String in the list at index `i-48`

It basically converts the ASCII characters 0 (48) through E (69) to the 0-indexed indices 0 through 21 with the i-48.

Kevin Cruijssen

Posted 2018-02-19T15:55:21.677

Reputation: 67 575

4

05AB1E, 142 68 66 65 bytes

`¶)•7/è¸ĀuVI{è:÷MDS.₁bö¼d@ÉÃƶõî›Λðë’OŒβι"žHƒö>“ÃaÈǝõöÓ∍¿þœθÀ•2ôèJ

Try it online!

-74 bytes thanks to EriktheOutgolfer, using a base-255 compressed string.

-2 bytes by reversing the compressed string to prevent having to concatenate three 0's

-1 byte thanks to EriktheOutgolfer, by switching two items in the input array in order to avoid the leading 0's, and thus removing the Reverse R command.

Kaldo

Posted 2018-02-19T15:55:21.677

Reputation: 1 135

4

Python 3, 162 147 144 142 138 127 bytes

lambda k,x=b'ABVCVDEFVGHIJKVVALVMNOVPEWQVGHRJKVASVVMTOV':"".join([(k+['\n',' '])[i-65]for i in x+x[5:16]+x[:4]+b'VDEWQVGHURJ'])

Try It Online

Special thanks to user202729 and Pavel.

Manish Kundu

Posted 2018-02-19T15:55:21.677

Reputation: 1 947

2

Retina 0.8.2, 115 bytes

^
12F5F:<=F?@ADEFF13F678F;<>F?@CDEFF14F698F:<=F?@ADEFF12F5F:<>F?@BCDF¶
{`1(?=.*¶(.*))
$1
^(.*)¶.*
$1
}T`1-E`0-D
F
¶

Try it online! Takes input as a newline-delimited list of strings.

Neil

Posted 2018-02-19T15:55:21.677

Reputation: 95 035

2

Stax, 59 58 bytes

îòÖ╥╬╬╞:,y╓ønä⌠╦╒ï╦≤x◘‼ε╩ⁿ◙ΓZ►e«qpôr╡"╣Ü≥┤╢┴;╡ÑkAú0:=;m╠╠x

Run and debug it

The corresponding ascii representation of the same program is this.

`ORIpY$T&z{m6Y=>mR)_ .VQ)eN70e[:0yO8j$^RN[ Bp{IN/$|"3^;G#^&lv!`FAx+@]p

`ORIpY$T&z{m6Y=>mR)_ .VQ)eN70e[:0yO8j$^RN[ Bp{IN/$|"3^;G#^&lv!` is a compressed literal with a value of "CDBGBLNOBQRSVWBBCEBHIJBMNPBQRUVWBBCFBHKJBLNOBQRSVWBBCDBGBLNPBQRTUVBB". The characters represent indexes into the token table. This program adds another token to represent a newline. It's not in the input, but added during execution. The rest of the program works like this.

F           for each character, execute the rest of the program
 A          integer literal 10, character code of newline
  x+        append 10 to the input array
    @       get element at index, using wrap-around
                the list is size 22, and B is 66, so B gets the first token
     ]      wrap the result in a singleton array.
                this effectively turns 10 into "\n"
      p     print without newline

recursive

Posted 2018-02-19T15:55:21.677

Reputation: 8 616

2

C (gcc) function, 139 bytes

i,m;f(char**s){for(i=0;i<68;)m="AB@E@JLM@OPQTU@@AC@FGH@KLN@OPSTU@@AD@FIH@JLM@OPQTU@@AB@E@JLN@OPRST@@"[i++],printf(m^64?"%s":"\n",s[m-65]);}

Try it online!

PrincePolka

Posted 2018-02-19T15:55:21.677

Reputation: 653

Nice. Can you explain the code? – arminb – 2018-03-06T13:35:31.690

@arminb Nothing too fancy, the long "AB@E..." String contains the indices of the tokens and newlines ABC... = token[012].. '@' = newline, A token or newline is printed as 'i' iterates through that string. – PrincePolka – 2018-03-06T20:25:17.043

merge the printf in for – l4m2 – 2018-04-20T11:07:53.380

1reverse the coding – l4m2 – 2018-04-20T11:09:21.337

1126 bytes – ceilingcat – 2018-06-28T20:37:57.527

1

Red, 133 bytes

foreach c{abzezjlmzopqtuzzaczfghzklnzopstuzzadzfihzjlmzopqtuzzabzezjlnzoprstzz}[prin either c =#"z"["^/"][t/(to-integer c -#"a"+ 1)]]

Try it online!

Ungolfed

t is a block with the list of tokens

s:{abzezjlmzopqtuzzaczfghzklnzopstuzzadzfihzjlmzopqtuzzabzezjlnzoprstzz}
foreach c s[                           ; for each character in s
    prin either c = #"z"               ; if it's a 'z' 
        ["^/"]                         ; print CR
        [t/(to-integer c - #"a" + 1)]  ; otherwise find which token to print
]                                      ; by mapping its offset to the alphabet

Galen Ivanov

Posted 2018-02-19T15:55:21.677

Reputation: 13 815

1

D, 166 bytes

import std.algorithm,std.range;T f(T)(T[]s){return"abvevjlmvopqtuvvacvfghvklnvopstuvvadvfihvjlmvopqtuvvabvevjlnvoprstvv".map!((int a){return(s~["\n"])[a-97];}).join;}

Try it online!

Ray

Posted 2018-02-19T15:55:21.677

Reputation: 1 488

1

Mathematica, 102 bytes

""<>Append[#,"
"][[36^^ajikrj7lg8pya7wgtt43pvrilsik1dea1uht6mx3go33m4mjj02hb4wi9w3~IntegerDigits~23]]&

Pure function. Takes a list of strings as input and returns a string as output. Just encodes all the token indices, similarly to other answers.

LegionMammal978

Posted 2018-02-19T15:55:21.677

Reputation: 15 731

1

Ruby, 97 bytes

->a{112.times{|i|$><<a[i%7-1+i%28/7*5]*("0@Xg(44k$,Xg0@Tz"[i/7].ord>>~i%7&1)+$/*(i%7/6+i%28/27)}}

Try it online!

Saved a few bytes with a different approach to most other answers.

The number of possible tokens in each line is as follows

Line number   Tokens 
1             4
2             5
3             5
4             7

The magic string contains one character per line, which is interpreted as a bitmap of which of up to 7 available tokens is to be printed for each of the 16 lines of the song.

a[i%7-1+i%28/7*5] iterates through the tokens of each line, shifting by 5 for each new line, and with an offset of 1 to account for the fact that the first line has only 4 tokens.

For lines 1-3 only the 64's through 4's bits are used - not using the 2's and 1's bits avoids printing tokens from the next line. for line 4, all 7 bits from 64's to 1's are used.

Level River St

Posted 2018-02-19T15:55:21.677

Reputation: 22 049