7
\$\begingroup\$

I have a new programming language called Brussels-Sprout. Brussels-Sprout functions in an array of 256 boolean values, all initialized to zero, has one instruction pointer, and one "bit index".

After each (non-branching) instruction is executed, the instruction pointer is incremented by one. If the instruction pointer goes off the right side of the instruction array, the program terminates. Going off the left side is undefined behavior.

If the bit index is outside the bounds of the array, it should be reset to 0.

Brussels-Sprout uses the following keywords, which are always lowercase:

chew - Invert the value in the array at the bit index. (flip the bit at the bit index)

swallow - Increment the bit index.

vomit - Decrement the bit index.

complain - Output the bit at the bit index to stdout, or equivalent output log.

feedtodog - If the bit at the bit index is 0, skip the next instruction. Otherwise, increment instruction pointer by 1.

playwithfood - If the bit at the bit index is 1, jump backwards 2 instructions. Otherwise, increment instruction pointer by 1.

If an instruction not on this list is executed, undefined behavior occurs.

I'm sure that this sounds like a very certain other turing-tarpit programming language. But since this programming language operates in boolean values and not bytes, I think it is different.

Test cases:

chew complain -> 1
swallow chew swallow chew swallow vomit complain playwithfood -> 11
chew complain swallow chew complain swallow chew complain swallow complain -> 1110
chew feedtodog undefinedbehaviour complain -> 1

Your challenge is to write an interpreter for Brussels-Sprout. This is code golf, so shortest program wins!

\$\endgroup\$
14
  • 2
    \$\begingroup\$ How do we get the input? Can we take it as a list? \$\endgroup\$
    – Riker
    Commented Apr 1, 2016 at 22:40
  • 2
    \$\begingroup\$ And do all the bits start at 0 or 1? \$\endgroup\$
    – Riker
    Commented Apr 1, 2016 at 22:42
  • 11
    \$\begingroup\$ If those are the only options for interacting with Brussels sprouts, clearly you haven't had them roasted with olive oil, salt, and pepper. \$\endgroup\$
    – Alex A.
    Commented Apr 1, 2016 at 22:45
  • 10
    \$\begingroup\$ Hey Mason! It is nice that you want to contribute to this site, but writing a good challenge is not easy and also requires some experience. 2 of your 3 challenges got closed so far and this one might be put on hold for being unclear as well. I would really recommend that you use the sandbox in the future, so you can get feedback and work potential flaws out before you post your challenge to the main site. However, I hope you stick around and have a great time here! \$\endgroup\$
    – Denker
    Commented Apr 1, 2016 at 22:46
  • 4
    \$\begingroup\$ Also you should really add some testscases, since this is not a very trivial task to solve and it's hard to say if a potential solution works correctly. But please note that testcases are not a replacement for a clear specification of the I/O formats which is definitely missing here. \$\endgroup\$
    – Denker
    Commented Apr 1, 2016 at 22:48

4 Answers 4

3
\$\begingroup\$

Python 3 2, 200 187 149 146 136 bytes

-9bytes thanks to Cyoce

def f(n,a=[0]*256,x=0,z=0):
 while 1:y=a[z];exec'a[z]^=~1 z+=1 z-=1 print-y/2 if~y:x+=1 if~~y:x-=3'.split()["wlipdy".find(n[x][3])];x+=1

Input as list, exits by error. Bonus feature: you can specify start array, start IP, and start DP in that very exact order.

\$\endgroup\$
12
  • \$\begingroup\$ A few suggestions: first, x=0;z=0 can be x=z=0. Second, a=[0 for x in range(256)] can be a=[0]*256. Third, instead of the if statement chain, use a dictionary of strings then use exec on the result. \$\endgroup\$
    – Cyoce
    Commented Apr 2, 2016 at 1:02
  • \$\begingroup\$ Did #1, I didn't know #2, considered #3. \$\endgroup\$ Commented Apr 2, 2016 at 1:10
  • \$\begingroup\$ Goodbye bytes! (I miss my fluffy) \$\endgroup\$ Commented Apr 2, 2016 at 1:11
  • \$\begingroup\$ Well 0 and -1, but yes, but I just got rid of those. But buts are confusing, but they're fun, so yeah. \$\endgroup\$ Commented Apr 2, 2016 at 1:16
  • \$\begingroup\$ I think you can save a few bytes by switching to Python 2 if you're interested (you can remove the parens on print and exec) \$\endgroup\$
    – Cyoce
    Commented Apr 2, 2016 at 1:19
1
\$\begingroup\$

SpecBAS (modern Sinclair BASIC interpreter) 202 Bytes

1 INPUT a$:DIM b(256)BASE 0,i$(),a$(SPLIT a$," "):DO 6:READ b,i$(b):LOOP:b=0,i=1:DO:c=b(b):EXECUTE i$(CODE a$(i,4)-99):b&=255,i+=1:LOOP:DATA 20,"b(b)=1-c",9,"b+=1",6,"b-=1",13,"?c;",1,"i+=c",22,"i-=3*c"

Or to make it a little clearer:

1 INPUT a$:
  DIM b(256) BASE 0,i$(),a$(SPLIT a$," "):
  DO 6:
    READ b,i$(b):
  LOOP:
  b=0,i=1:
  DO:
    c=b(b):
    EXECUTE i$(CODE a$(i,4)-99):
    b&=255,i+=1:
  LOOP:
  DATA 20,"b(b)=1-c",9,"b+=1",6,"b-=1",13,"?c;",1,"i+=c",22,"i-=3*c"

Uses some features that weren't available in the 80s, so there's that. Also shameless rips off some of the techniques in other entries. Sorry about that!

Input is from the user at runtime. Execution ends with an error "Subscript wrong".

\$\endgroup\$
0
\$\begingroup\$

Java 8

1. Relaxed version (301 283 280 277 275 bytes)

Golfed as this:

class C{static int i,j,x,b[]=new int[256];public static void main(String[]z){Runnable[]r=new Runnable[26];r[20]=()->b[i]=-~x;r[9]=()->i++;r[6]=()->i--;r[13]=()->System.out.print(x);r[1]=()->j+=x;r[22]=()->j-=3*x;for(;;){x=b[i];r[z[j].charAt(3)-99].run();i*=~(i>>8)&1;j++;}}}

Somewhat ungolfed version (whitespaces and comments added):

class C {
    // Declared as static so they may be changed inside the lambdas without the compiler complaining about that.
    // i is the bit index and j is the instruction pointer.
    // x is just to avoid refering to b[i] in order to save 3 bytes.
    // b is our array. Uses ints instead of booleans to save bytes and use some clever math tricks.
    static int i, j, x, b[] = new int[256];

    public static void main(String[] z) {

        // An array of lambdas. The index is the ascii code of 4th letter of the command name subtracted from 99.
        // Thanks for CatsAreFluffy for telling about the 4th letter trick.
        Runnable[] r = new Runnable[26];
        r[20] = () -> b[i] = -~x; // chew
        r[9] = () -> i++; // swallow
        r[6] = () -> i--; // vomit
        r[13] = () -> System.out.print(x); // complain
        r[1] = () -> j += x; // feedtodog. It is 1 or 0 instead of 2 and 1 due to the j++ down there.
        r[22] = () -> j -= 3 * x; // playwithfood. It is -3 or 0 instead of -2 and +1 due to the j++ down there.

        // This is the interpreter itself. Runs forever (or until an exception is raised).
        for (;;) {
            x = b[i];

            // Fetch an instruction and runs it. May throw an exception or execute some arbitrary instruction if the instruction name is unknown or was mistyped.
            r[z[j].charAt(3) - 99].run();

            // Resets the bit index if out of range.
            i *= ~(i >> 8) & 1;

            // Next instruction. No special treatment for branching needed because they already considers this.
            j++;
        }
    }
}

We surely should have testcases. I am not sure if there is some bug hiding out there.

Anyway I run it with that (input is given as command line arguments):

chew complain swallow chew complain swallow chew complain swallow complain

And here is the output:

1110
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
    at C.main(C.java:1)

The ArrayIndexOutOfBoundsException is the standard way to finish the program, it is not a bug!

BTW, this answer abuses the fact that the 4th char of each command is different than each other (thanks CatsAreFluffy). This means that whew is interpreted as chew and that yellow is interpreted as swallow.

2. Strict version (354 337 334 331 329 bytes)

If strict conformance to command names are required (and just looking for the 4th letter in command's name is not enough), then I have this alternative similar answer with 329 bytes:

import java.util.*;class C{static int i,j,x,b[]=new int[256];public static void main(String[]z){List o=Arrays.asList("chew","swallow","vomit","complain","feedtodog","playwithfood");Runnable[]r={()->b[i]=-~x,()->i++,()->i--,()->System.out.print(x),()->j+=x,()->j-=3*x};for(;;){x=b[i];r[o.indexOf(z[j])].run();i*=~(i>>8)&1;j++;}}}

Somewhat ungolfed version (whitespaces and comments added):

// Needed for java.util.List and java.util.Arrays.
import java.util.*;

class C {
    // Declared as static so they may be changed inside the lambdas without the compiler complaining about that.
    // i is the bit index and j is the instruction pointer.
    // x is just to avoid refering to b[i] in order to save 3 bytes.
    // b is our array. Uses ints instead of booleans to save bytes and use some clever math tricks.
    static int i, j, x, b[] = new int[256];

    public static void main(String[] z) {

        // Declared as a list so we can use the indexOf method further down. Screw up the generics.
        List o = Arrays.asList("chew", "swallow", "vomit", "complain", "feedtodog", "playwithfood");

        // An array of lambdas.
        Runnable[] r = {
            () -> b[i] = -~x, // chew
            () -> i++, // swallow
            () -> i--, // vomit
            () -> System.out.print(x), // complain
            () -> j += x, // feedtodog. It is 1 and 0 instead of 2 and 1 due to the j++ down there.
            () -> j -= 3 * x // playwithfood. It is -3 and 0 instead of -2 and +1 due to the j++ down there.
        };

        // This is the interpreter itself. Runs forever (or until an exception is raised).
        for (;;) {
            x = b[i];

            // Fetch an instruction and runs it. Throws an exception on unknown or mistyped instructions.
            r[o.indexOf(z[j])].run();

            // Resets the bit index if out of range.
            i *= ~(i >> 8) & 1;

            // Next instruction. No special treatment for branching needed because the branching instructions already considers this.
            j++;
        }
    }
}
\$\endgroup\$
10
  • \$\begingroup\$ I don't Java, but can you shorten the list of strings by using a separator then splitting it into an array? i.e. javaSplitFunction("chew|swallow|vomit|complain|feedtodog|playwithfood|") \$\endgroup\$
    – Cyoce
    Commented Apr 2, 2016 at 1:07
  • \$\begingroup\$ @Cyoce I could simply use an array instead and it would be easier and shorter, but then this screws me up further down when I have to use the List.indexOf method. To fix that screw-up, I would end with a longer answer. \$\endgroup\$ Commented Apr 2, 2016 at 1:11
  • 1
    \$\begingroup\$ Can you use a HashMap from Strings (or char) to Runnables? The fourth char of each command is distinct. \$\endgroup\$ Commented Apr 2, 2016 at 1:24
  • \$\begingroup\$ @Cyoce No, because doing that would violate java's type system and produce a compile error. :( \$\endgroup\$ Commented Apr 2, 2016 at 1:52
  • 1
    \$\begingroup\$ @VictorStafusa nevermind I'm stupid I forgot those were booleans. \$\endgroup\$
    – Cyoce
    Commented Apr 2, 2016 at 2:44
0
\$\begingroup\$

Ruby 2, 151 bytes

Saw this because of another golf challenge and was amused enough by it to write it up in Ruby, and was happy to see it got very close to the Python answer (Ruby usually doesn't golf compress quite as well as Python).

b=[n=i=0]*256
r=''
(x=b[i=b[i]?i:0]
eval({?w=>'b[i]=1-x',?l=>'i+=1',?i=>'i-=1',?p=>'r<<x.to_s',?d=>'n+=-x',?y=>'n+=x*-3'}[c[n][3]])
n+=1)while(c[n])
r

You can put this in a function def that takes 'c' as a list of the commands, and it returns 'r' as the last line which is the result string.

Runs the testcases properly (if the second one is updated to actually output 110 instead of 11 as it currently incorrectly claims is the right answer - see my comment above).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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