# Let us play the ocarina

As we all know, the Zelda series are one of the best game series ever made. In honor of that, let us play some songs on the ocarina.

## Challenge:

Write a program which, given a song, outputs the score to stdout for that particular song.

## Input:

The song which you will have to output the score of will be given by a unique three character combination as seen below:

zel - Zelda's Lullaby
sas - Saria's Song
eps - Epona's Song
sos - Sun's Song
sot - Song of Time
sst - Song of Storms


Bonus songs, -7 % each:

mof - Minuet of Forest
bof - Bolero of Fire
sow - Serenade of Water
nos - Nocturne of Shadow
ros - Requiem of Spirit
pol - Prelude of Light


Bonus song 2, -8 %:

scs - Scarecrow's song


As we all know, the Scarecrow's song is a song you compose yourself. This song needs to have eight notes. Output a score you compose yourself which is different from all the other scores.

If you decide to include all songs, it will total to a -50 % bonus to your byte score.

## Output:

The notes in the output are symbolized by the following characters:

^
<
>
V
A


Output a score on the following format:

-^-^-^-^-^-^-^-^-
-<-<-<-<-<-<-<-<-
->->->->->->->->-
-V-V-V-V-V-V-V-V-
-A-A-A-A-A-A-A-A-


Only one note per column is allowed. For simplicity's sake I've added another row to the original four rows.

Each note correspond to a different row:

^: ----------------
<: ----------------
>: ----------------
V: ----------------
A: ----------------


Output shall be written to stdout. Trailing newlines are allowed.

## Examples:

Input (Zelda's Lullaby):

zel


Output:

---^-----^-------
-<-----<---------
----->----->-----
-----------------
-----------------


Input (Bolero of Fire):

bof


Output:

-----------------
-----------------
--------->--->---
-V---V-----V---V-
---A---A---------


Note cheat sheet:

zel
<^><^>
sas
V><V><
eps
^<>^<>
sos
>V^>V^
sot
>AV>AV
sst
AV^AV^
mof
A^<><>
bof
VAVA>V>V
sow
AV>><
nos
<>>A<>V
ros
AVA>VA
pol
^>^><^


Since we play the ocarina code golf, the shortest program in bytes wins!

## Song references:

http://www.thonky.com/ocarina-of-time/ocarina-songs

http://www.zeldadungeon.net/Zelda05-ocarina-of-time-ocarina-songs.php

• Perhaps you should use a % bonus rather than a byte bonus. It's practically impossible to encode any of these songs in <7 bytes, so none of the bonuses would currently be worth it. You should also mention that the Scarecrow song should be composed of 8 actual notes; otherwise someone could just print an empty score. But other than that, nice challenge! Sep 23 '15 at 19:30
• The fact that I can hear these songs in my head reading this question makes me wonder what I'm doing with my life. I mean, I'm at work when I could be playing OoT... Sep 23 '15 at 21:45
• I hope this doesn't invalidate any existing answers, but note that in the original Zelda the scarecrow's song must be composed of two different notes, so e.g. AAAAAAAA would not be a valid scarecrow's song.
– Jan
Sep 23 '15 at 22:19
• I think lowercase v would look better. Sep 23 '15 at 22:30
• I'm really waiting to see is anyone solve this problem in vellato or fugue and play it on ocarina Sep 24 '15 at 10:13

# Funciton, 4322 − 50% = 2161

Not really trying to golf here. Going more for the beauty angle. I think the main program looks really neat, a perfect rectangular box tucked away on the right.

As always, you can get a better rendering by executing $('pre').css('line-height',1) in your browser console.  ┌─────────────────────────┐ ┌─┴─╖ ┌─┴─╖ ┌────────┤ · ╟─────────────────────┤ · ╟─────────────┐ ╔═════════╗ ╔════╗ ╔════╗ │ ╘═╤═╝ ╔═════════╗ ╘═╤═╝ ╓───╖ │ ║ 1257283 ║ ┌─╢ 40 ║ ║ 25 ║ │ │ ║ 2097151 ║ ├───╢ ʫ ╟───┐ │ ║ 6456094 ║ │ ╚════╝ ╚══╤═╝ ┌─┴─╖ │ ╚════╤════╝ ┌─┴─╖ ╙─┬─╜ ┌─┴─╖ │ ║ 8219021 ║ │ ┌───╖ ┌─┴─╖ ┌───┤ · ╟────────┴────┐ └─────┬────┤ · ╟───┴───┤ · ╟─┤ ║ 4660190 ║ └──┤ × ╟───┤ % ║ │ ╘═╤═╝ │ ┌┴┐ ╘═╤═╝ ╘═╤═╝ │ ╚════════╤╝ ╘═╤═╝ ╘═╤═╝ │ │ │ └┬┘ │ │ │ ╔═══╗ ┌─┴─╖ ┌──┴─╖ ╔═╧═╗ │ │ ╔═══╗ ┌────╖ │ ┌─┴─╖ ┌┐ │ │ │ ║ 8 ╟──┤ ʫ ╟──┤ >> ║ ║ ║ │ │ ║ 1 ╟─┤ >> ╟─┘ ┌───┤ ? ╟─┤├─┤ │ │ ╚═══╝ ╘═╤═╝ ╘══╤═╝ ╚═══╝ │ │ ╚═══╝ ╘══╤═╝ │ ╘═╤═╝ └┘ │ │ │ ╔════════════════╧═════════╗ │ │ ┌─┴─╖ ┌───╖ ┌─┴─╖ ┌─┴─╖ ╔═╧═╗ │ │ ║ 609678112368778425678534 ║ │ ┌─┴─────────┤ ʫ ╟─┤ ‼ ╟─┤ · ╟─┤ ‼ ║ ║ 1 ║ │ │ ║ 616189712722605554111376 ║ │ │ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╚═══╝ │ │ ║ 461573643915077926310571 ║ │ │ │ │ │ ╔═╧══╗ │ │ ║ 355541007599150245813976 ║ │ │ ╔══════╗ │ │ └───╢ 45 ║ │ │ ║ 426564826002362964111793 ║ │ │ ║ 2097 ║ │ ┌─┴─╖ ┌───╖ ╚════╝ │ │ ║ 714054902293682079346275 ║ │ │ ║ 1565 ║ └───┤ · ╟─┤ ♭ ╟─┐ │ │ ║ 663973372550500581508544 ║ │ │ ╚═╤════╝ ╘═╤═╝ ╘═══╝ ├────────────────────┘ │ ║ 874263187322344354338195 ║ │ │ ┌─┴─╖ ┌─┴─╖ │ │ ║ 642609790172899326178321 ║ │ │ │ ‼ ╟─────────┤ ? ╟───────┘ │ ║ 071643306454414932126243 ║ │ │ ╘═╤═╝ ╘═╤═╝ │ ║ 308860823981077902637848 ║ │ ┌─┴─╖ ┌─┴─╖ ╔═══╗ ┌─┴─╖ │ ║ 322657399386789617074176 ║ └─┤ · ╟─┤ ʫ ╟─╢ 8 ║ ┌─┤ ? ╟────────────────────────────────┘ ╚══════════════════════════╝ ╘═╤═╝ ╘═╤═╝ ╚═══╝ │ ╘═╤═╝ │ ┌───┴╖ ╔════╗ │ ╔═══╗ └─┤ >> ╟─╢ 21 ║ └─╢ 0 ║ ╘════╝ ╚════╝ ╚═══╝  Continuing in the tradition of giving Funciton functions names consisting of a single, strange, rarely-used Unicode character, I thought about what could best represent this challenge, and it occurred to me that Link and Zelda (or, if you want, Legend of Zelda) give you LZ, so the lower-case digraph ʫ (U+02AB, ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ʟᴢ ᴅɪɢʀᴀᴘʜ) seems appropriate. # Explanation As explained in the esolangs article, the Funciton program receives the input encoded as what I would call “UTF-21”, but as a single humongous integer. If I wanted to use this number as a key to a hashmap (dictionary, associative array), I’d need a hash function that satisfies two criteria: one, it’s simple enough to implement in Funciton, and two, all of the 13 expected input strings give a different hash value. The simplest hash function I could think of was input % m for some value of m. Therefore, I tried m = 13, 14, 15, etc. until I got to the smallest integer for which all the hash values are unique. Turns out this number is 25. The hash values are: zel = 6 sas = 19 eps = 10 sos = 22 sot = 1 sst = 9 mof = 14 bof = 3 sow = 13 nos = 17 ros = 21 pol = 16 scs = 23  We encode each song by having one bit represent the presence or absence of a note. For example, Zelda's Lullaby would be encoded as follows: ---^-----^------- = 01001000 -<-----<--------- = 10010000 ----->----->----- = 00100100 ----------------- = 00000000 ----------------- = 00000000  except that the bits are in the opposite order; the top left cell is in the least significant bit. This means every song is 40 bits long. We thus create a (moderately sparse) hash table by taking a 40×25 = 1000-bit number and placing the bit pattern for each song in the right place according to its hash value. The monstrous number in the program is exactly this hash table. Here’s what each of the remaining numbers mean: • 45 = 0x2D is the Unicode for -. • 1257283645609482190214660190: This is the string ^<>VA in UTF-21. In hindsight I could have used 7 bits per character here, making the number shorter, but UTF-21 is so deeply traditional in Funciton that it simply didn’t occur to me. • 2097151 = 0x1FFFFF = (1 << 21) − 1. Used to get the first character from the above string. • 20971565: This is the string -\n, which is appended to the end of each line. • It may seem curious that this number and the previous look so similar, but if you think about it, it’s because we’re using decimal and the Unicode for \n happens to be 10. That last number is (10 << 21) + 45. The program now proceeds as follows: • The main program calls ʫ with the following 3 parameters: • B: The hash table, shifted right by 40 bits times the hash value of the input. The song we want to output is now in the 40 least significant bits. • c: The string ^<>VA. • a: The number 8. • In each iteration of ʫ, • if c is not empty, • if a is not zero, look at the bottom bit of B. Output -, followed by another - if it is zero or the first character of c otherwise. Shift right B by one to remove one bit and decrement a. • if a is zero, output -\n, then chop off the first character from c and start another loop with a = 8. • if c is empty, we are done. • Well done, that's impressive! Sep 24 '15 at 17:39 • <grumble>That dang musical flat... throwing off the monospacing...</grumble> Sep 24 '15 at 20:09 • @iAmMortos: Agreed. For this reason, I avoided the ♭ character for a long time and convinced myself that I could just bitwise-not, then ♯, then bitwise-not. But now I use Deja Vu Sans Mono to edit Funciton and it has ♭. So now all we need is for StackExchange to switch to that font for code too ;-) Sep 24 '15 at 23:15 • Also, you surely must admit that there’s no better fitting Unicode character for decrement and increment than ♭ and ♯. They’re just perfect. Sep 24 '15 at 23:16 • Haha, totally. I don't know anything about Function, but that makes total sense! Sep 24 '15 at 23:16 # Python 2, 143.5 (287 bytes - 50%) i='^<>VA' u=dict(zel="<^>"*2,sas="V><"*2,eps="^<>"*2,sos=">V^"*2,sot=">AV"*2,sst="AV^"*2,mof="A^<><>",bof="VAVA>V>V",sow="AV>><",nos="<>>A<>V",ros="AVA>VA",pol="^>^><^",scs="<"*8)[raw_input()] r=[17*['-']for _ in[1]*5] x=0 for g in u:r[i.find(g)][x*2+1]=g;x+=1 for h in r:print''.join(h)  The grid is generated with dashes; then indexed and replaced with notes. • Haven't looked into it too much but you can save bytes in the declaration of j by replacing each comma with a space and calling split with no arguments Sep 23 '15 at 20:30 • I don't think you needed to do that, it's still your algorithm so I think you deserve the rep, but anyway I managed to get rid of range. Sadly you can't just multiply the inner list by 5 because they are all the same object and changing one changes the others :/ We beat perl (for now) though! Sep 23 '15 at 21:19 • Couldn't you eliminate 6 bytes (1 for each of the first six songs) by doing stuff like "<^><^>" => "<^>"*2? Sep 24 '15 at 1:18 • scs="<"*8 I don't like your Scarecrow song. Sep 24 '15 at 18:59 • When I try to run this it just halts on line 2 and never finishes. Sep 25 '15 at 21:15 # Pyth, 56.5 (113 bytes − 6 × 7% − 8%) VtJ" ^<>VA"+K\-sm+?qNdNKK@LJj@jC"þØí§V^G¤×¹z1«bëë¶ñRõr¤çM"1391423xcs@LGjC"cc0Á:xqç÷\rS Íó×º:9"lG3z6  It contains unprintable characters, so here is a reversible xxd hexdump: 0000000: 5674 4a22 205e 3c3e 5641 222b 4b5c 2d73 VtJ" ^<>VA"+K\-s 0000010: 6d2b 3f71 4e64 4e4b 4b40 4c4a 6a40 6a43 m+?qNdNKK@LJj@jC 0000020: 2207 fe85 d880 ed0e a756 5e47 8ba4 d7b9 "........V^G.... 0000030: 7a9e 0531 ab1b 62eb ebb6 f112 52f5 72a4 z..1..b.....R.r. 0000040: e74d 2231 3339 3134 3233 7863 7340 4c47 .M"1391423xcs@LG 0000050: 6a43 229a 6317 6330 c13a 9278 71e7 10f7 jC".c.c0.:.xq... 0000060: 5c72 5309 87cd f3d7 ba3a 3922 6c47 337a \rS......:9"lG3z 0000070: 36 6  You can also try it online. ## Explanation I store the songs in base-6 numbers, re-encoded to base 1391423 and then base 256 to save space. I had to choose base 6 since some of the songs start with ^, and numbers can't really start with a 0 after decoding.  J" ^<>VA" save characters in J t discard the space V loop over all characters C"..." parse base256 string (songs) to int j 1391423 convert to base 1391423 (separate songs) C"..." parse base256 string (codes) to int j lG convert to base-26 @LG replace indices by corresponding letters s concatenate c 3 chop to 3-character codes x z find index of input code @ get correct song j 6 convert to base 6 @LJ replace indices by corresponding ^<>VA m map d over the above ?qNdNK take the current character if at its row, otherwise a dash + K add a dash s concatenate +K\- add a dash and print  # Perl 5, 125 (320260 250 Bytes -6x7% bonus songs -8% scarecrow song) Yay, finally an opportunity to experiment with that Perlish hash syntax. $_=pop;@B={qw(zel <^><^> sas V><V>< eps ^<>^<> sos >V^>V^ sot >AV>AV sst AV^AV^ mof A^<><> bof VAVA>V>V sow AV>>< nos <>>A<>V ros AVA>VA pol ^>^><^ scs <^V>>V^<)}->{$_}=~/./g;map{@L=('-')x17;for$i(0..@B){$L[1+2*$i]=$_,if$B[$i]eq$_}say@L}qw(^ < > V A)


### Test

$perl -M5.010 ocarina.pl scs ---^---------^--- -<-------------<- ------->->------- -----V-----V----- -----------------  • Use the qw() syntax instead of the fat commas ( %h=qw(zel <^><^> sas >'V><' ...) to save some bytes – mob Sep 24 '15 at 16:42 • @mob That advice shaved more than just "some" bytes. :) Thanks! Sep 24 '15 at 18:10 • @L can be written more succinctly as @L=('-')x17. Also, the main hash can be left anonymous as @B={qw(zel <^><^> ... scs <^V>>V^<)}->{$_}=~/./g. Sep 25 '15 at 2:00
• I see, those are nice tricks to avoid the slightly verbose split function. Ten more bytes were sacrified to the void. tumbs up Sep 25 '15 at 7:04

# Perl, 75 (150 bytes - 50%)

#!perl -nl
$i=vec~$_,0,32;print+qw(- - ^ < > V A)[0,map{vec('w2W4F4w7DeweTFwR$Ew$C2wVdeVe3cw4B#EEVVwC5Tw44bwR&e',$i/480%15*8-$_,4)==$.&&$.,0}1..8]while$.++<6  Counting the shebang as 2, input is taken from stdin. Sample usage $ echo zel | perl zelda.pl
---^-----^-------
-<-----<---------
----->----->-----
-----------------
-----------------

$echo bof | perl zelda.pl ----------------- ----------------- --------->--->--- -V---V-----V---V- ---A---A---------$ echo scs | perl zelda.pl
-----------------
---<-<-<---------
-----------------
-----------V-V---
-A-------A-----A-

• Using the bitshifting vec function for this? Amazing. Sep 25 '15 at 7:08
• @LukStorms I wish it could do 3 bits, rather than only powers of 2 ;) Sep 25 '15 at 7:31

# Haskell, 344 - 50% = 172 bytes

import Data.List
s"zel"=82
s"sas"=69
s"eps"=86
s"sos"=48
s"sot"=128
s"sst"=50
z"mof"=11055
z"bof"=373854
z"sow"=1720
z"nos"=73217
z"ros"= -12730
z"pol"=4791
z"scs"=304236
z n=s n*126
p n|n*n== -n="   "|0<1="A^<>V"!!(nmod5):p(ndiv5)
o=putStr.unlines.transpose.(l:).concatMap(\c->[map(e c)"^<>VA",l]).take 8.p.z
e c d|c==d=c|0<1='-'
l="-----"


o does the job.

Thought I could beat Python by using these encodings (took me a long time ._.), but no. They don't really save a lot of bytes yet. Any suggestions?

Yes, that is a minus in front of the encoding for "ros". Thats because its 'sheet' ends with the character that means 0 in my base-5, because this negative trick wouldn't work for the 'easy songs' encoded by doubling what's encoded in s. Unless you use quot maybe, but then you can't handle p (-1) specially, since quot (-5) = 0, so the negativity would vanish. Whatever.

# PHP: 130 bytes (260 270279 bytes − 6 × 7% − 8%)

Thanks to Ismael Miguel and Blackhole for some great ideas to save more bytes!

<?php $f=str_split;for($z='*^<>VA';++$i<6;print"- ")foreach($f(base_convert(substr(current(preg_grep("/^$argv[1]/",$f(bofttmmeps8jf0mofvff0nosfnfopol99d0rosyxt0sasrgk0scs8m8msosm9p0sotnry0sowylc0sstybp0zeldk90,7))),-4),36,6),1)as$c)echo$i-$c?'--':'-'.$z[$c-0];  After the print"-, this is a literal insertion of a carriage return. It may translate to two bytes in Windows. All bonus songs including the Scarecrow's song are included. Each song is represented in seven bytes of code. I like the new scoring because with the old scoring I would have gained just one meager bonus point overall! The recent edits make PHP generate a lot of warnings, so to keep things nice and tidy, those are diverted to /dev/null. Save as zelda.php and run on the command line: $ php zelda.php zel 2> /dev/null
---^-----^-------
-<-----<---------
----->----->-----
-----------------
-----------------

$php zelda.php bof 2> /dev/null ----------------- ----------------- --------->--->--- -V---V-----V---V- ---A---A---------$ php zelda.php scs 2> /dev/null
-^-------^-------
---<-------<-----
----->------->---
-------V-------V-
-----------------

• Did you mean "save as main.php"? Sep 23 '15 at 20:16
• @ZachGates - Thanks for catching that, changes made.
– user15259
Sep 23 '15 at 20:17
• You don't need the () around ($i-$c) on echo($i-$c)?'--':'-'.$z[$c-0];. Also, your string inside your split can be used without '. And '/^'.$argv[1].'/' can be written as "/^$argv[1]/" Sep 23 '15 at 22:59
• Thank you! I think it's allowed in CGSE to pipe warnings to /dev/null to clean up the output?
– user15259
Sep 24 '15 at 13:30
• @Blackhole - thank you! It's tied with the Perl 5 submission, doing pretty good...
– user15259
Sep 24 '15 at 20:46

# Python 3 - 138.5 (292280 277 bytes - 50%)

Shaved a few bytes off the current Python leader while doing the print-as-you-go method rather than the replace method.

Try Online

s=dict(zel="<^><^>",sas="V><V><",eps="^<>^<>",sos=">V^>V^",sot=">AV>AV",sst="AV^AV^",mof="A^<><>",bof="VAVA>V>V",sow="AV>><",nos="<>>A<>V",ros="AVA>VA",pol="^>^><^",scs="AV><^AV>")[input()]
s+=" "*8
for c in "^<>VA":
o="-"
for x in range(8):o+=["--",c+"-"][s[x]==c]
print(o)


Run:

> python3 loz.py
bof [return]


Output:

-----------------
-----------------
--------->--->---
-V---V-----V---V-
---A---A---------

• You can save a few bytes by using ['--',c+'-'][s[x]==c] instead of the conditional Sep 25 '15 at 10:15
• Ooh, good call, thank you! Sep 25 '15 at 12:39

# Ruby, rev 1, 192 - 50% = 96

Golfing includes:

removal of whitespace between groups of letters in the magic string (and revision of the denominator at the end of the line to /4.) Removal of some other unnecessary whitespace.

conversion of the escape sequences into single characters (stack exchange will not display them, so I have put ? as a placeholder)

redefinition of g as a single string containing five runs of 17 - followed by newlines, instead of an array of five strings of 17 -

s=gets.chop
s[?s<=>s[0]]=''
n=("owEkrswuns=;gcsbfbYuze33as&&es77os??otaast??mf?9pl
?"=~/#{s}/)/4
g=(?-*17+'
')*5
(n<4? n+5:6).times{|i|x=$'[i/3].ord/5**(i%3)%5;g[x*18+i*2+1]='^<>VA'[x]} puts g  # Ruby, rev 0, 223 - 50% = 111.5 (ungolfed) The input code is reduced to 2 letters. If it begins with an s, the s is deleted, if it begins with a letter after s (only applicable to zel the last letter is deleted, and if it begins with a letter before s the middle letter is deleted. The magic string (which in the ungolfed version contains spaces for clarity) contains the 2-letter codes followed by the music data. It is searched using the match operator =~ which returns the position in the string. There is exactly one song each of 5, 7, and 8 notes (plus scs which also has 8 notes.) These, along with one arbitrary 6-note song ros are bundled at the beginning of the magic string so that the value of n given by the position in the string can be used to calculate the number of notes to play. cs is squeezed in before bf, and with the truncation when the number in n is rounded down we just get away with the correct calculation for both. After the fourth cluster, all songs have 6 notes so if n is large the number of notes is reduced to a default of 6. An array of - is set up for output and the notes are substituted in one by one. The required music data is extracted from the variable $' which contains the part of the original magic string to the right of the match. In this way, irrelevant data is ignored.

The notes are encoded 3 at a time into the magic string, just after the relevant 2-letter song code. They are extracted with division by 5**(i%3) and a character in g is updated accordingly. At the end of the program g is printed.

s=gets.chop
s[?s<=>s[0]]=''
n=("owEk rswu ns=;g csbfbYu ze33 as&& es77 os\21\21 otaa st\23\23 mf\35\71 pl\n\a"=~/#{s}/)/5

g=(0..4).map{'-'*17}
(n<4? n+5 : 6).times{|i|x=\$'[i/3].ord/5**(i%3)%5;g[x][i*2+1]='^<>VA'[x]}
puts g


# Python 2, 141.5 Bytes -50% (283 Bytes)

s='D  2)AE0*  A2)D  AD )2 A  )D2A 0,"!A D2) A  (2EA"4H !A )2D A 1F(A)2D  A  p\xc5*'.split("A")['sst pol zel sos sot sow sas ros mof scs nos eps bof'.split().index(raw_input())]
for c,n in zip(s,"^<>VA"):print"-".join([("-"+n)[i>"0"]for i in bin((ord(c)-32)%255)[2:].zfill(8)][::-1])


Stores each note as a byte as each line is 8 notes long. Recalls the binary representation and then replaces with the right characters.

# Lua, 249 bytes - 50% = 124.5

w=io.write for j=1,5 do n={sst=41881,pol=44915,zel=30814,sos=42315,sot=17577,sow=5953,sas=35588,ros=11065,mof=29335,nos=122170,eps=29729,bof=719576,scs=999999}[...]for i=1,8 do d=n%6 n=(n-d)/6 c=d==6-j and'AV><^':sub(d,d)or'-'w('-',c)end w('-\n')end
`

Pretty simple, just reads back songs encoded as base-6 numbers.