Make a Unicorn interpreter

25

1

Recently, I made a made a typo and I wrote unicorn instead of unicode, I did what any normal person would do and I made an esolang out of it. In this challenge you will be writing a Unicorn interpreter.

Because Unicorn programs are horrible long, you'll have to write a short interpreter to compensate for this.

Example

These are the transpiled result, not the actual interpreted result your program should output


1

                                                      
alert([x=(p=prompt())/2+Math.sqrt(p*p/4-prompt()),p-x])

              
"Hello, World!"

Specification

  • Unicorn is divided into "sections" which are space-separated
  • Each section represents a character
  • The number of unicorns () in each section is converted to it's associated character (i.e. 32 unicorns -> chr(32) -> ).
  • If the section contains goats (), the length of the amount of goats should be doubled, then converted to the associated character
  • If the section contains any other characters, the program should ignore the character.
  • Each section (character) should be joined to form a program
  • This resulting program should be evaluated in the language you have written the program in. (e.g. JavaScript's eval, Python's exec)
  • Unicorns are unicode U+1F984; goats are unicode U+1F410.
  • If you choose a compiled language, you may output/save the compiled, compiled unicorn code

(unicorns) and (goats) all count as one byte for this challenge.

If your language doesn't support emojis, you may identify unicorns as (u) and goats as (g). You may not support emojis and u,g


If you really want to see the unicodes unicorns, here is a picture of this post


+50 bounty: to the shortest program in (the original) Unicorn while being under 6500 chars. You must use this version, it must run on Firefox, Chrome, or Safari.

Downgoat

Posted 2015-12-28T21:58:51.867

Reputation: 27 116

17

I didn't know unicorns were that shape.

– Doorknob – 2015-12-28T22:00:13.020

5@Doorknob冰 This is the era of rectangular unicorns! – TanMath – 2015-12-28T22:01:35.983

@Doorknob冰 ssshhh, don't hurt the unicorn's feelings (I'll update the post) – Downgoat – 2015-12-28T22:01:49.857

Do you know if your bonus is possible? Meaning, have you tried to do your own bonus? – TanMath – 2015-12-28T22:10:26.770

@TanMath I'm very sure it's possible. I've tried and with minimal golfing I've come close – Downgoat – 2015-12-28T22:11:09.457

Can you tell us the code points of those characters? – SuperJedi224 – 2015-12-28T22:12:30.607

@SuperJedi224 "Unicorns are unicode U+1F984; goats are unicode U+1F410." The code points depending on which encoding and number of bytes will differ. You can use this site for the bytes across different encodings

– Downgoat – 2015-12-28T22:13:39.813

@Doᴡɴɢᴏᴀᴛ is it absolutely necessary for me to have the unicode character show up? It does not render for me... – TanMath – 2015-12-28T22:17:35.030

@Maltysen no, you'll need to execute it as a Pyth program – Downgoat – 2015-12-28T22:18:49.193

4

For those who can't see the unicorn and goat on this page, unicorn and goat.

– El'endia Starman – 2015-12-28T22:19:59.420

Does evaluation of the resulting program have to be independent of the unicorn interpreter environment? E.g. in C the resulting program a) needs to provide a main function and b) gets it's own fresh global scope. – nimi – 2015-12-28T22:34:32.750

@nimi hmm, didn't consider that, if you write it in a compiled language, I guess you could output/save the compiled unicorn program. If you write it in an interpreted language, it doesn't need it's own environment but it's fine if it does – Downgoat – 2015-12-28T22:35:59.310

1@insertusernamehere that depends on your language, if your language can handle Unicode characters within the code then sections may be as long as unicode supports. If your language supports ASCII only characters within the code, sections will never be longer than 127 unicorns. – Downgoat – 2015-12-28T22:39:10.347

@nimi the character – Downgoat – 2015-12-28T22:49:09.027

Could you include a few test cases? I get a6er:[<=8=8rom8:))/2+Ma:4.sqr:8*8/-8rom8:))8-<]) for your diamond code. – Dennis – 2015-12-28T22:49:31.930

@Dennis sure give me a minute (or 5) to write some up – Downgoat – 2015-12-28T22:51:12.783

@Maltysen I mean the transpiled code, not the end result. – Dennis – 2015-12-28T22:55:16.640

16I can see the goats, but not the unicorns. Are they hiding, or are the goats not letting me see the unicorns? – Rɪᴋᴇʀ – 2015-12-28T23:11:23.837

@RikerW The goats must of scared the unicorns away :( I'll add a picture of the post – Downgoat – 2015-12-28T23:12:11.107

Thanks. If I didn't believe in unicorns I would wonder why my browser shows goats but not unicorns. – Rɪᴋᴇʀ – 2015-12-28T23:41:06.137

14On my computer, this language should be called "Funny Unicode Boxes". – cat – 2015-12-29T00:40:43.093

Oh, wait, people already made jokes to that effect, never mind. – cat – 2015-12-29T00:41:08.327

1nice unicorns B) – cat – 2015-12-29T00:50:18.727

1I'm pretty sure 6500 chars is impossible unless you go for the ug approach which still will take a lot – ev3commander – 2015-12-29T01:38:31.333

1"This resulting program should be evaluated in the language you have written the program in." So no self-hosting Unicorn interpreter, then? It'd be Unicorn all the way down... – Tim Pederick – 2015-12-29T05:22:14.610

1

In fact they are invisible pink unicorns.

– alephalpha – 2015-12-29T05:26:16.483

You did ask for the length of the amount of goats, doubled, correct? – LegionMammal978 – 2015-12-29T11:05:08.647

No compiled languages? Sad. :( – Kroltan – 2015-12-29T13:15:59.820

Can we include rainbows and sparkles in the unicorn code? – ev3commander – 2015-12-29T13:46:55.023

1Does each section contain only goats or only unicorns? If not, if we have section uugg that's \x06, right? – Sherlock9 – 2015-12-29T14:44:19.667

2I did what any normal person would do and I made an esolang out of it. I love it haha – Ikaros – 2015-12-29T17:45:13.373

Can we use the latest version of Unicorn with the rainbows and more for the bounty? – TanMath – 2016-01-01T20:05:19.570

@TanMath no you must use the specified version – Downgoat – 2016-01-01T20:05:51.587

Can we use Unicorn => Pyth? – ev3commander – 2016-01-02T19:04:53.900

@BlockCoder1392 for the bonus? No, you must use JavaScript Unicorn – Downgoat – 2016-01-02T19:05:27.223

I thought so. I was just making sure – ev3commander – 2016-01-02T19:06:03.490

https://www.youtube.com/watch?v=T3U9hFaPl5w – 12Me21 – 2017-01-28T17:05:09.013

Answers

9

Pyth - 23 17 bytes

.vsmC+/d\y/d\cz

Try it online.

It works by splitting the input by spaces, then for each section counting the number of unicorns and number of goats * 2 then adding them, then taking the char at the code point. It finished by summing the char array and pyth-evaling.

Maltysen

Posted 2015-12-28T21:58:51.867

Reputation: 25 023

21

Unicorn (ES6), 5934 5278 bytes

Under the custom encoding, this is 5278 bytes (1 byte per char); but with UTF-8, it would 4 bytes per char (though only 1 for a space), or 20869 total.

(too many Unicorns and Goats to reasonably display here)

Instead, here's a pastebin. This Unicorn code transpiles to this JS snippet:

s=>eval(s.replace(/\S+ ?/g,c=>String.fromCharCode(c.length>>1<<c.charCodeAt()%2)))

Now, this isn't the shortest possible version; this is shorter:

s=>eval(s.replace(/\S+ ?/g,c=>String.fromCharCode(c.length>>1<<("">c))))

However, the one unicorn in there would transpile to 56034 goats, thus multiplying the score by roughly 11.

Here's the function I used to transpile to Unicorn:

function g(s){return s.replace(/./g,function(c){i=c.charCodeAt();return(i%2?"".repeat(i):"".repeat(i/2))+" "}).slice(0,-1)}
<textarea id=O cols=100></textarea><button id=P onclick="Q.value=g(O.value);R.innerHTML=(Q.value.length+Q.value.split(' ').length-1)/2">Run</button><br><textarea id=Q rows=10 cols=100>Output appears here.</textarea><br><p>Length: <span id=R>0</span><br></p>

Note: I haven't actually tested the program, as there isn't an online interpreter that I could find (although I suppose I could hook up the .js file to HTML...?)

ETHproductions

Posted 2015-12-28T21:58:51.867

Reputation: 47 880

How is it that this answer with over 5KB is voted higher than the answer with 17 bytes? – OldBunny2800 – 2015-12-30T13:33:57.580

1

@OldBunny2800 Because unicorns.

– ETHproductions – 2015-12-30T14:36:41.213

4

Python 179 176 bytes

EDIT: I just learnt s.split(' ')=s.split()

Here is the second "actual" programming language Unicorn interpreter. I call this version of Unicorn "UnicornPy" pronounced as "unicorn pie". I am making this much too official!

s=raw_input()
s=s.replace('','')
s=s.replace('','u')
for i in s:
    if i not in "ug ":
        s=s.replace(i,'')
s=s.split()
for i in s:
    s[s.index(i)]=chr(len(i))
exec(''.join(s))

For some reason, it needs me to convert the unicorn and goat emojis to u and g. I do not know why.

Try it here!

TanMath

Posted 2015-12-28T21:58:51.867

Reputation: 1 431

1Dennis' website is called "Try it online!" and the phrase isn't copyrighted... – Alex A. – 2015-12-29T03:38:44.353

6@AlexA. it was a joke! – TanMath – 2015-12-29T04:10:41.040

Javascript uses UTF-16 (I think), so the unicorn and goat are actually 2 characters each. – 12Me21 – 2017-01-30T22:04:09.917

1@12Me21 no one in the history of PPCG has counted javascript as UTF-16. – Pavel – 2017-01-31T00:45:51.123

I meant that strings in JS are stored as UTF-16 – 12Me21 – 2017-01-31T00:49:21.567

Don't you mean s.split(" ") === s.split()? :) – connectyourcharger – 2019-06-21T14:55:26.497

3

Ruby, 78 Bytes

eval ARGV[0].gsub(/[^ug ]/,'').split.map{|b|(b.size*(b[0]=='u'?1:2)).chr}.join

It basically reads the first command line argument, splits it at every space character, maps the size of the block to the appropriate character and joins it all together.

Edit: Forgot the requirement that all other characters should be ignored

BDA

Posted 2015-12-28T21:58:51.867

Reputation: 31

Now it does... thank you for mentioning! – BDA – 2015-12-29T21:07:19.987

3

Unicorn ES6 (Invalid), 3379 bytes

This is invalid because it uses the latest version of Unicorn with rainbows, sun with clouds, and sparkles. Thanks to @ETHproductions for the JS code to interpret unicorn.

code is in the paste bin below

Pastebin: http://pastebin.com/raw/Q9Kd4ixA
This is only 3379 bytes if sparkles, sun/clouds, and rainbows also are 1 byte.

ev3commander

Posted 2015-12-28T21:58:51.867

Reputation: 1 187

1

Racket, 200 bytes

(define(f s)(eval(read(open-input-string(list->string(map integer->char(map(λ(x)(foldl(λ(y a)(case y[(#\u)(add1 a)][(#\g)(+ a 2)]))0 x))(map string->list(string-split s)))))))(make-base-namespace)))

Ungolfed:

(define(f s)
  (eval(read(open-input-string
             (list->string ;;back to string
              (map integer->char ;;back to char
                   (map(λ(x)
                         (foldl(λ(y a)
                                 (case y
                                   [(#\u)(add1 a)]
                                   [(#\g)(+ a 2)]))
                               0 x))
                       (map string->list (string-split s))))))) ;;splitting by space, converting to list of chars
       (make-base-namespace)))

It starts by splitting the string into list of strings by spaces, then creates a list of chars per splitted string. Then each list of chars is reduced into a number by adding 1 if unicorn, 2 if goat. Finally, each list containing the sum is made a list of chars, then a string which is passed to eval.

Try it online!

Rodrigo Ruiz Murguía

Posted 2015-12-28T21:58:51.867

Reputation: 81

Welcome to the site! One of the mods on the site has made a website to run programs online (the Racket page: https://tio.run/nexus/racket). You can paste your code in there (maybe adding to header or footer if Racket needs anything extra to make a complete program out of a function) and then get a link that you can add to this answer. This is not necessary but it is nice for people who want to test your code.

– 0 ' – 2017-01-30T17:58:08.650

@1000000000 I have just added it, thanks for the tip! – Rodrigo Ruiz Murguía – 2017-01-30T18:27:16.243

1

JavaScript, 140 154 141 bytes

var s='';i.split(" ").forEach((e)=>{s+=String.fromCharCode((e.split("").length-1)+2*(e.split("").length-1));});console.log(eval(s));

It splits the input string in an array of strings, using space as a needle. It then proceeds to count the amount of unicorns and goats*2 and concatenate the summed result to what will be evaluated.

More readable:

var s = '';
i.split(" ").forEach((e) => {
    s+=String.fromCharCode((e.split("").length-1)+2*(e.split("").length-1));
});
console.log(eval(s));


Edit:

Updated code to accept an argument from CLI, use: node unicorn.js " "

var s='';process.argv[2].split(' ').forEach((e)=>{s+=String.fromCharCode((e.split('').length-1)+2*(e.split('').length-1));});console.log(eval(s));

Ungolfed:

var s = '';
process.argv[2].split(' ').forEach((e) => {
    s+=String.fromCharCode((e.split('').length-1)+2*(e.split('').length-1));
});
console.log(eval(s));


Edit 2:

Edited to accept input as a function parameter, use node unicorn.js

i=>{var s='';i.split(' ').forEach((e)=>{s+=String.fromCharCode((e.split('').length-1)+2*(e.split('').length-1));});return eval(s);};

Ungolfed:

i =>{
    var s = '';
    i.split(' ').forEach((e) => {
        s+=String.fromCharCode((e.split('').length-1)+2*(e.split('').length-1));
    });
    return eval(s);
};

Try it online!

Alvaro Arregui

Posted 2015-12-28T21:58:51.867

Reputation: 131

Welcome to Programming Puzzles & Code Golf! We require all answers to be either full programs (e.g. taking input through prompt()) or functions (taking input through a function parameter: i=>{var s='';...}). – ETHproductions – 2017-01-30T19:26:46.463

Edited my answer to accept the input as an argument – Alvaro Arregui – 2017-01-30T20:30:38.343

1

RProgN, 25 bytes

~`''R'(+)%s*'{Lc}R do

Explained

~                             # Zero Space Segment
 `                         # The String literal ""
   ''                   # The String literal ""
       R                     # Replace, turning all goats into twonicorns
        '(+)%s*'          # The pattern string "(+)%s*", which is "A fewnicorns, then as much whitespace as possible, or none.
                 {Lc}R      # Replace with the result of the function, which converts the captured subgroup to it's Length, then to a char.
                       do   # Straight up do it.

Once again, RProgN falls into the trap of being consistently okay.

Try it online!

ATaco

Posted 2015-12-28T21:58:51.867

Reputation: 7 898

1

PHP, 83 80 86 87 bytes

Now Unicorn-ready

For the cost of 3 bytes I made this unicorn ready:

$a=mb_substr_count;foreach(explode(" ",$argv[1])as$b)echo chr($a($b,)+2*$a($b,));

Takes an input from command line, like:

$ unciorns.php " "

This will output 32.

Demo

Try before buy


Unfortunately OS X 10.10.5 doesn't support is hiding Unicorns. Here's the alternative ug-approach (80 bytes):

$s=substr_count;foreach(explode(' ',$argv[1])as$c)echo chr($s($c,u)+2*$s($c,g));

Takes an argument from command line, like:

$ php unicorns.php "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuug uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu"

Try the ug-version


Edits

  • Saved 1 byte due to massive refactoring. This version is already discarded again, since I managed to golf the original even further:

Demo discarded version (86 bytes)

for($_=$argv[1].' ';$c=$_[$i++];)$t+=u==$c?1:(g==$c?2:(' '==$c?-$t+!print chr($t):0));
  • Saved 6 bytes by replacing for with foreach
  • Added 3 bytes making it Unicorn-ready.

insertusernamehere

Posted 2015-12-28T21:58:51.867

Reputation: 4 551

1

Mathematica, 118 bytes

a=StringCount;ToExpression@FromCharacterCode[If[#~StringTake~1=="u",#~a~"u",2IntegerLength[#~a~"g"]]&/@StringSplit@#]&

Performs exactly as described in the specification. I couldn't use emoji in Mathematica string literals without the interpreter exploding, so I used u and g.

LegionMammal978

Posted 2015-12-28T21:58:51.867

Reputation: 15 731

1

Rust, 426 bytes

use std::io::Write;macro_rules!c{($n:expr,$a:expr)=>(println!("{}",std::str::from_utf8(&std::process::Command::new($n).arg($a).output().unwrap().stdout).unwrap());)}fn main(){let d:String=std::env::args().skip(1).next().unwrap().split(' ').map(|s|s.chars().fold(0u8,|a,c|a+match c as char{''=>1,''=>2,_=>0}) as char).collect();std::fs::File::create("o").unwrap().write_all(d.as_bytes()).unwrap();c!("rustc","o");c!("o","");}

This probably can be golfed the hell down, but type safety and checked errors are quite verbose.

Since Rust is a compiled language, this program outputs the decoded program to a file and invokes the compiler on said file, then executes the resulting binary.

Ungolfed:

use std::io::Write;

macro_rules! command {
    ($name:expr,$argument:expr) => (println!("{}", std::str::from_utf8(
        std::process::Command::new($name)
                              .arg($argument)
                              .output()
                              .unwrap()
    ));)
}

fn main() {
    let decoded: String = std::env::args()
        .skip(1) //ignore program name
        .next().unwrap().split(' ') //get first arg split on spaces
        //transform every section in a char
        .map(|section| section.chars()
            .fold(0u8, |accumulator, chr| accumulator + match chr as char {
            '' => 1,
            '' => 2,
            _ => 0
        }) as char)
        //convert iterator to string
        .collect();

    std::fs::File::create("o").unwrap()
        .write_all(decoded.as_bytes()).unwrap();
    command!("rustc", "o");
    command!("o", "");
}

Kroltan

Posted 2015-12-28T21:58:51.867

Reputation: 517

Actually, the emoji are 4 bytes each in UTF-8. – LegionMammal978 – 2015-12-29T14:37:09.823

@LegionMammal978 I mistakenly used char-count instead of byte count :P – Kroltan – 2015-12-29T14:39:10.660

The entire program is 394 bytes. – LegionMammal978 – 2015-12-29T14:40:46.630

@LegionMammal978 It just increased even more. What tool do you use to count bytes? – Kroltan – 2015-12-29T14:43:42.057

1

I use this.

– LegionMammal978 – 2015-12-29T14:45:10.307

1Actually, for this challenge the emjoi count as one byte so the char count is thr same as the byte count. – TanMath – 2015-12-29T16:12:55.553

1

Python 3, 94 86 bytes

This is a simple parser that works even if you mix u and g in one section.

s=input().split();exec(''.join(chr(sum([[0,2][j<"u"],1][j>"g"]for j in i))for i in s))

As an example (using u and g in separate sections):

gggggggggggggggggggggggggggggggggggggggggggggggggggggggg ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu ggggggggggggggggggggggggggggggggggggggggggggggggggggggg gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg gggggggggggggggggggg uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

should parse to

print(1)

Sherlock9

Posted 2015-12-28T21:58:51.867

Reputation: 11 664

1

Ruby, 75 characters

A nifty ruby interpreter that replaces all with ' ' (a space) and all with ' ' (two spaces), and gets the length of each segment.

I call this version of Unicorn RubyUnicorn Rubycorn.

->s{eval s.split(a=' ').map{|r|r.gsub('',a).gsub('',a*2).size.chr}.join}

MegaTom

Posted 2015-12-28T21:58:51.867

Reputation: 3 787

Rubycorn, possibly? – Kroltan – 2015-12-31T18:30:20.757

@Kroltan that is a cooler name. – MegaTom – 2016-01-02T17:44:04.533

0

Perl 6, 67 bytes

{use MONKEY-SEE-NO-EVAL;EVAL [~] .words».&{chr m:g/\/+2*m:g/\/}}

smls

Posted 2015-12-28T21:58:51.867

Reputation: 4 352

0

SmileBASIC, 125 bytes

INPUT S$WHILE LEN(S$)R=ASC(POP(S$))IF R-32THEN C=C+!(R-117)+2*!(R-103)ELSE O$=CHR$(C)+O$C=0
WEND
SAVE"TXT:@",CHR$(C)+O$EXEC"@

Using PRGEDIT to execute the code without saving would have been a lot nicer, but also a lot longer.

code:

INPUT CODE$ 'making the user type 1000s of characters just so I could save 2 or 3
WHILE LEN(CODE$)
 CHAR$=POP(CODE$) 'I convert the code backwards, since POP( is shorter than SHIFT(
 IF CHAR$==" " THEN
  UNSHIFT OUT$,CHR$(CHAR)
  CHAR=0
 ELSE
  INC CHAR,(CHAR$=="u")+(CHAR$=="g")*2
 ELSE
WEND
SAVE "TXT:@",CHR$(CHAR)+OUT$
EXEC "TXT:@"

12Me21

Posted 2015-12-28T21:58:51.867

Reputation: 6 110