Programming with Bits and Bytes

40

6

In this challenge you are going to write an interpreter for a simple language I've made up. The language is based on a single accumulator A, which is exactly one byte in length. At the start of a program, A = 0. These are the languages instructions:

!: Inversion

This instruction simply inverts every bit of the accumulator. Every zero becomes a one and every one becomes a zero. Simple!

>: Shift Right

This instruction shifts every bit in A one place to the right. The leftmost bit becomes a zero and the rightmost bit is discarded.

<: Shift Left

This instruction shifts every bit in A one place to the left. The rightmost bit becomes a zero and the leftmost bit is discarded.

@: Swap Nybbles

This instruction swaps the top four bits of A with the bottom four bits. For example, If A is 01101010 and you execute @, A will be 10100110:

 ____________________
 |                  |
0110 1010    1010 0110
      |_______|

That's all the instructions! Simple, right?

Rules

  • Your program must accept input once at the beginning. This will be a line of code. This is not an interactive interpreter! You can only accept input once and do not have to loop back to the start once that line has been executed.
  • Your program must evaluate said input. Every character that is not mentioned above is ignored.
  • Your program should then print out the final value of the accumulator, in decimal.
  • Usual rules for valid programming languages apply.
  • Standard loopholes are disallowed.
  • This is , smallest byte count wins.

Here are some small programs to test out your submissions. Before the arrow is the code, after it is the expected result:

  • ! -> 255
  • !>> -> 63
  • !<@ -> 239
  • !nop!&6*! -> 255

Enjoy!

bitsnbites

Posted 2015-09-07T14:10:23.820

Reputation: 621

I'm presuming from ! -> 255 that we're to use 8 bits per byte here? The question isn't explicit. – Toby Speight – 2015-09-09T12:10:02.287

3@TobySpeight A byte, by definition, is 8 bits. – HyperNeutrino – 2016-02-15T00:30:06.243

Answers

15

Pyth, 36 35 bytes

u%@[t_G/G2yGi_jGJ16JG)x"!><@"H256z0

Test harness

The internal representation of the accumulator is an integer. This integer is mod-ed by 256 on each iteration, as desired. The operations performed are -G-1, G/2, G*2 and G converted to base 16, reversed, and converted back to base 10, where G is the accumulator.

I missed the line about ignoring everything else. This has been remedied. Thanks, @Dennis.

isaacg

Posted 2015-09-07T14:10:23.820

Reputation: 39 268

So -G-1 is shorter than ~G in Pyth? I somewhat doubt that. – CalculatorFeline – 2017-06-21T01:30:18.377

The code in question is actually t_G, where _ is negation and t is -1. In Pyth, ~ means something totally different. – isaacg – 2017-06-21T01:47:03.327

I meant Python ~ (bitwise NOT) – CalculatorFeline – 2017-06-21T01:48:52.683

@CalculatorFeline My point was there is no 1-character function with that effect in Pyth, so the above code (at least for that operation) is as good as it's going to get. – isaacg – 2017-06-21T01:49:49.770

13

C, 96

Assuming ASCII (or compatible) input:

a;main(c){while(c=getchar()+1)a=(c^34?c^61?c^63?c^65?a:a*257/16:a/2:a*2:~a)&255;printf("%u",a);}

Tidier:

a;
main(c){
  while(c=getchar()+1)
    a=(c^34?
      c^61?
        c^63?
          c^65?
            a
          :
            a*257/16
        :
          a/2
      :a*2:~a
    )&255;
  printf("%u",a);
}

Basically it's just a collection of nested ternary expressions. I'm incrementing the value obtained from getchar() so that an EOF (-1) results in a value of zero and the program exits.

(ideone link)

r3mainer

Posted 2015-09-07T14:10:23.820

Reputation: 19 135

1I tried the challenge myself and I wrote almost exactly the same code. Btw. your program doesn't drop the bit when shifting upwards (input: !<> should result in 127 and not 255). Either define your a as char, or use the line a&=255 (and use %u) to get the correct effect. Also you can shorten your negation a^255 to ~a. a>>4&15 is also shorter than your (a&240)/16. – MarcDefiant – 2015-09-08T12:53:38.150

Ah, good point. Turns out it was more efficient to mask out the lower 8 bits at each iteration. – r3mainer – 2015-09-08T13:10:13.430

1In this case you can even use the format string %u instead of %hhu – MarcDefiant – 2015-09-08T13:19:15.430

1I just saw it now, but you can also use a/16|a*16 instead of a/16|(a&15)*16. The few bits on top get removed by the &255. – MarcDefiant – 2015-09-08T13:27:18.957

1A tiny improvement: a*257/16 is one byte shorter than a/16|a*16. – Toby Speight – 2015-09-09T12:37:27.330

@TobySpeight Nice one, thanks! – r3mainer – 2015-09-09T15:24:49.033

11

Python 3, 133 bytes

Uses a dictionary to make up for a lack of switch-case syntax in Python. See more here.

a="0"*8
for i in input():a={"!":''.join(str(1-int(b))for b in a),"<":a[1:]+"0",">":"0"+a[:-1],"@":a[4:]+a[:4]}.get(i,a)
print(int(a,2))

The accumulator is a string which is converted into a base 10 number at the end.

Example I/O:

$ python3 bitsnbytes.py
!
255
$ python3 bitsnbytes.py
!>>
63
$ python3 bitsnbytes.py
!<@
239
$ python3 bitsnbytes.py
!nop!&6*!
255

Beta Decay

Posted 2015-09-07T14:10:23.820

Reputation: 21 478

If it was a real, interactive interpreter, it would be for i in sys.stdin: :) – Zizouz212 – 2015-09-07T16:15:53.650

4@Zizouz212 I believe you mean if it was interactive; it looks like a real interpreter to me. ;) – Alex A. – 2015-09-07T16:25:11.930

9

Javascript (ES6), 80 91 90 bytes

a=>[...a].reduce((p,c)=>c=='!'?p^255:c=='<'?p*2%256:c=='>'?p>>1:c=='@'?p/16|0+p%16*16:p,0)

Pretty much as short as it can get. Defines an anonymous function which takes the program as input.

  • For !, takes x XOR 255, as JS's ~ would consider x a 32-bit number.
  • For <, multiplies x by 2 and takes the result mod 256.
  • For >, truly shifts the bits of x 1 bit to the right.
  • For @, floors x/16 and adds it to x%16*16.

Thanks to @vihan for suggesting the use of reduce to save a byte.

ETHproductions

Posted 2015-09-07T14:10:23.820

Reputation: 47 880

You can use < to save around 4 bytes. Using reduce might also save some bytes – Downgoat – 2015-09-07T16:52:51.757

1@vihan Do you mean < in place of ==? If so, that wouldn't work, as no-op characters would incorrectly perform an operation. I used that in my previous, 80-byte solution. – ETHproductions – 2015-09-08T01:26:17.273

Isn't ES6 fat arrow standard on PPCG that you have to define it? – MayorMonty – 2015-09-09T00:09:15.637

@SpeedyNinja I don't know of any such standard, but if you could point me to a post about one, I'll modify my answer. – ETHproductions – 2015-09-09T03:05:01.233

8

CJam, 37 bytes

0q{"!><@"#"~ 2/ 2* GmdG*+ "S/=~255&}/

Try it online in the CJam interpreter.

How it works

0                   e# Push 0 (accumulator).
q                   e# Read from STDIN.
{                   e# For each character in the input:
  "!><@"#           e#   Find its index in "!><@" (-1 if not found).
  "~ 2/ 2* GmdG*+ " e#   Push that string.
  S/                e#   Split at spaces to push ["~" "2/" "2*" "GmdG*+" ""].
                    e#     "~"      : signed 64-bit bitwise NOT
                    e#     "2/"     : divide by 2
                    e#     "2*"     : multiply by 2
                    e#     "GmdG*+" : (x) -> (x/16) (x%16) -> (16(x%16) + (x/16))
                    e#     ""       : NOOP
  =~                e#  Select the corresponding string and evaluate it.
  255&              e#  Zero all but the 8 least significant bits.
}/                  e#

Dennis

Posted 2015-09-07T14:10:23.820

Reputation: 196 637

8

Java (8), 514 483 411 366 359 239 224 229 198 194 187 186 184 182 181 180 177 characters

Wow, this has been golfed down a LOT! Thanks to everyone who gave me suggestions! I greatly appreciate it!

interface T{static void main(String[]g)throws Exception{int i,a=0;while((i=System.in.read())!=10)a=(i==33?255-a:i==62?a/2:i==60?a*2:i==64?a>>4|a<<4:a)%256;System.out.print(a);}}

Golfed 31 (!) bytes by optimizing the nibble swap with bitwise operations as opposed to lengthy Integer.??? methods.

Golfed 72 (!!!!) chars by removing the unnecessary string created to swap nibbles. Much better than before!?

Golfed 45 (!!) chars by removing use of java.util.Scanner and reading from System.in directly. Note that now that the lambda expression is gone, Java 8 is no longer required! Just merely Java 1 would do!

Golfed 7 chars by making class (default) (removed public keyword), thanks to @bmarks

Golfed 120 (!!!!!!!) chars by turning all those lengthy Integer class operations in the bit flipping to 255 - a. Now that's much shorter!

Golfed 15 (!) chars by converting shifts to multiplication and division, removing the braces from the while statement, and making a local within the main method.

Ungolfed 9 =( chars because of a problem with the left shift not discarding the leftmost byte. Therefore, I now do mod (256). The right shift will make the resulting number one bit shorter than before, so there is no need to use mod on right shift. My nibble-swap thing will swap the last 4 bits and the second-last nibble, and the and (&) truncates all other bits. My inversion program doesn't cause any problems if the original number is less than 256.

Golfed 31 35 chars thanks to @Geobits by converting switch statement to a lot of ternary statements, and also converting chars to ints, shortening the literals.

Golfed 7 chars by removing unnecessary &240 in the nibble swap ((a&240)>>4 to a>>4 and converting (a&15)<<4 to a<<4&240. The last change only golfed one character though.

Golfed 1 char by removing unnecessary = in a /= 2, because a = a /= 2 is equivalent to a = a / 2.

Golfed 2 chars by turning println to print.

Golfed 2 chars by removing accidental a= in a=255-a (a=a=255-a is equivalent to a=255-a)

Golfed 1 char by turning a<<4&240 into a%16<<4.

Golfed 1 char by adding brackets to the outside of the ternary statement and doing %256. That way, the %16 is unnecessary in the left-shift part of the nibble swap. The brackets add 2 chars and the %16 saves 3 chars.

Golfed 3 chars by changing class to interface and removing public using Java 8's static interface method feature. Thanks to @TheNumberOne (no comment, but find his answer on "Tips for golfing in Java"

HyperNeutrino

Posted 2015-09-07T14:10:23.820

Reputation: 26 575

I don't think the class has to be public. Also, I think if you make a an Integer instead of an int, you could do a.parseInt, a.toString, etc. instead of Integer.parseInt,Integer.toString, etc. – bmarks – 2015-09-08T03:02:54.337

Thanks for the first suggestion; I'm going to remove all Integer class methods though. – HyperNeutrino – 2015-09-08T23:18:37.847

Perhaps you can do while((i=System.in.read())>10) instead of !=10 to save a byte? – bmarks – 2015-09-09T00:29:49.040

Good idea, but then anything below 10 will cause the program to terminate, and I'm supposed to ignore other characters, not make then the end of the world (or at least my program:)) I'll consider it though; perhaps there are no valid ascii characters below 10. – HyperNeutrino – 2015-09-09T00:33:47.477

Ah, indeed my suspicions were correct. A tabulator is (char) 9. – HyperNeutrino – 2015-09-09T00:35:13.063

4It's almost never worth it to use a switch while golfing. The case/break are just too long. You should be able to save a bunch by making the whole thing a ternary; something like a=i=='!'?255-a:i==62?a/2:i=='<'?a*2%256:i=='@'?(a&240)>>4|(a&15)<<4:a; – Geobits – 2015-09-09T13:51:29.413

@Geobits Thanks a lot! You saved me 31 characters! – HyperNeutrino – 2015-09-09T21:20:20.953

Whoops, I mean 35 characters. – HyperNeutrino – 2015-09-09T21:22:01.487

7

Rust, 121 115 bytes

fn r(s:&str)->u8{let mut n=0u8;for t in s.chars(){match t{'!'=>n=!n,'>'=>n/=2,'<'=>n<<=1,'@'=>n=n>>4|n<<4,_=>()}}n}

Sample run:

fn main() {
    println!("{}", r("!"));    //=> 255
    println!("{}", r("!>>"));  //=> 63
    println!("{}", r("!<@"));  //=> 239
}

Ungolfed:

fn run_ungolfed(s: &str) -> u8 {
    let mut n = 0u8;
    for t in s.chars() {
        match t {
            '!' => n = !n,
            '>' => n >>= 1,
            '<' => n <<= 1,
            '@' => n = (n >> 4) | (n & 15) << 4,
            _ => ()
        }
    }
    n
}

Surprisingly short for Rust. Nothing else really interesting other than the fact that I learned more precedence rules today—who knew (a>>b)|c is the same as a>>b|c?

Shaved off a byte by changing n>>=1 to n/=2; however, the same cannot be done with multiplication, because arithmetic overflow is a panic (i.e. crash) in Rust.

Doorknob

Posted 2015-09-07T14:10:23.820

Reputation: 68 138

2The precedence thing makes sense when you convince yourself that >> is sort of like division and | is sort of like addition. – Lynn – 2015-09-07T20:23:08.527

6

Python 2, 79 bytes

I realized that I have done something very similar to this in Python earlier. This is just a port of my Ruby answer, but it is incidentally the shortest Python answer as of now :D

a=0
for i in raw_input():a=[~a,a/2,a*2,a*16+a/16,a]["!><@".find(i)]&255
print a

The difference from the Ruby version is that this one doesn't ignore invalid instructions while iterating over the input. Instead I take advantage of the fact that Python tends to return -1 instead of nil when there is no match -- The current value of a is appended to the back of the result array, so that all invalid instructions maps to the same, unchanged value.

daniero

Posted 2015-09-07T14:10:23.820

Reputation: 17 193

6

HP 41C/CV/CX (? bytes, 42 steps)

Purely for giggles, here it is for the HP 41C/CV/CX calculator. (Requires either the Extended Functions module, or a 41CX for the ATOX function.) The calculator doesn't report program sizes in bytes, unfortunately.

Put your program into the Alpha register, which is a little tricky, as there's no way to enter ! or @ directly from the keyboard (use XTOA with the ASCII codes 33 and 64 respectively to append them).

Steps 08 and 10 allow for ignoring invalid opcodes; remove them to save 2 steps, but the program will crash on invalid input.

01 LBL"BB
02 0
03 LBL A
04 ATOX
05 X=0?
06 GTO E
07 X<>Y
08 SF 25
09 XEQ IND Y
10 CF 25
11 GTO A
12 LBL 33
13 255
14 X<>Y
15 -
16 RTN
17 LBL 60
18 2
19 *
20 256
21 MOD
22 RTN
23 LBL 62
24 2
25 /
26 INT
27 RTN
28 LBL 64
29 RCL X
30 16
31 /
32 INT
33 X<>Y
34 16
35 *
36 256
37 MOD
38 +
39 RTN
40 LBL E
41 RDN
42 RTN

db2

Posted 2015-09-07T14:10:23.820

Reputation: 161

4

Python 3, 124 94 93 bytes

a=0
for i in input():
 if i in"!><@":a=(i=='!')*(255-a)+(i==">")*a//2+(i=="<")*(a+a)%256+(i=="@")*(16*(a%16)+a//16)
print(a)

"!" is same as subtracting from 255.
"<" is same as multiplying by 2. But 8 bit register means mod 256.
">" is same as integer division by 2.
"@" means shifting last 4 bits (a%16) by 4 bits(*16) and adding the first four bits(a/16).

EDIT (read shameless copying)
Saw the other answer in python (by Beta decay). It uses a really effective way to simulate switch cases using dictionary. Using that we can write

a=0
for i in input():a={"!":255-a,"<":a<<1&255,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)
print(a)

Thanks, Beta Decay.

Rohcana

Posted 2015-09-07T14:10:23.820

Reputation: 210

No matter what operation you do, you have to reduce mod 256 right? So why not do that at the end: a={"!":255-a,"<":a*2,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)%256. This immediately saves you a byte (because you'll do a*2 instead of a<<1)...but @daniero's answer also shows that if you do it this way then (a%16)<<4 can be shortened to just a<<4, because any bit 16 or larger will be eliminated once you multiply it by 16 and reduce it mod 256. Nice! Also, you can now replace 255-a by -1-a...or better, by just ~a. Altogether, these suggestions should save you 9 bytes. – mathmandan – 2015-09-09T06:06:46.357

3

Haskell, 89 bytes

a#'!'=255-a
a#'>'=div a 2
a#'<'=mod(a*2)256
a#'@'=mod(a*16)256+div a 16
a#_=a
f=foldl(#)0

Usage example: f "!>>" -> 63

nimi

Posted 2015-09-07T14:10:23.820

Reputation: 34 639

3

Ruby, 81 73 bytes

So much simpler -- no eval! For each valid character in the input, it evaluates each instruction, and finds the appropriate instruction through the index of $& (the current character in the input).

a=0
gets.scan(/[!><@]/){a=[~a,a/2,a*2,a*16+a/16]["!><@".index$&]&255}
p a

daniero

Posted 2015-09-07T14:10:23.820

Reputation: 17 193

1That's genius. Much shorter that any other way. 2 upvotes by me! – edc65 – 2015-09-09T06:44:47.400

How can you double upvote...? – HyperNeutrino – 2015-09-12T15:40:07.613

@JamesSmith He's probably referring to this and my python answer :)

– daniero – 2015-09-12T17:46:47.750

@danerio I see. – HyperNeutrino – 2015-09-12T17:54:38.160

3

Python 3, 127 bytes

Edit: shorting, thanks @Jakube

Edit2: fix, thanks @Anachor

a=0
for i in input():a=(a^255if i=="!"else a>>1if i==">"else a<<1if i=="<"else(a&15)<<4|(a&240)>>4if i=="@"else a)&255
print(a)

uno20001

Posted 2015-09-07T14:10:23.820

Reputation: 321

Maybe this is because windows' new line. That's plus two bytes. I'll use that byte counter next time. :-) Thanks. – uno20001 – 2015-09-07T18:32:36.863

Note that this doesn't discard the leftmost bit when left shifting, so !< gives 510 while it should be 254 – Rohcana – 2015-09-07T18:48:22.430

I hope now it does. Sorry for my mistakes, this is my first "golf" challenge. – uno20001 – 2015-09-07T19:05:59.837

3

Rust, 111 bytes

More of a comment on @Doorknob's answer, but I don't have any rep for comments as I just created an account.

One can shave 10 bytes off his Rust solution with the following:

fn r(s:&str)->u8{let mut n=0u8;for t in s.chars(){n=match t{'!'=>!n,'>'=>n>>1,'<'=>n<<1,'@'=>n>>4|n<<4,_=>n}}n}

user4867444

Posted 2015-09-07T14:10:23.820

Reputation: 275

I thought we could get even shorter using fold (https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold) but surprisingly makes it a tad longer.

– user4867444 – 2015-09-07T18:41:12.197

3

Ceylon, 297 290

shared void y(){value t=process.readLine()else"";variable Byte a=0.byte;for(c in t){switch(c)case('!'){a=a.not;}case('>'){a=a.rightLogicalShift(1);}case('<'){a=a.leftLogicalShift(1);}case('@'){a=a.and(#f0.byte).rightLogicalShift(4).xor(a.and(#f.byte).leftLogicalShift(4));}else{}}print(a);}

Formatted:

shared void y() {
    value t = process.readLine() else "";
    variable Byte a = 0.byte;
    for (c in t) { switch (c)
        case ('!') { a = a.not; }
        case ('>') { a = a.rightLogicalShift(1); }
        case ('<') { a = a.leftLogicalShift(1); }
        case ('@') { a = a.and(#f0.byte).rightLogicalShift(4).xor(a.and(#f.byte).leftLogicalShift(4)); }
        else {} }
    print(a);
}

#f and #f0 are hexadecimal numbers for the nibbles, .byte converts an integer into a byte. I'm lucky that Byte's .string attribute already uses the unsigned representation of a byte. Ceylon also features a switch statement without fall-through, and a string is a list of characters, which can be iterated.

I also tried to cut those long shift method names down by using an aliasing import, but this actually becomes 7 bytes longer:

import ceylon.language{Byte{r=rightLogicalShift,l=leftLogicalShift}}shared void x(){value t=process.readLine()else"";variable Byte a=0.byte;for(c in t){switch(c)case('!'){a=a.not;}case('>'){a=a.r(1);}case('<'){a=a.l(1);}case('@'){a=a.and(#f0.byte).r(4).xor(a.and(#f.byte).l(4));}else{}}print(a);}

Formatted:

import ceylon.language {
    Byte {
        r=rightLogicalShift,
        l=leftLogicalShift
    }
}
shared void x() {
    value t = process.readLine() else "";
    variable Byte a = 0.byte;
    for (c in t) {
        switch (c)
        case ('!') { a = a.not; }
        case ('>') { a = a.r(1); }
        case ('<') { a = a.l(1); }
        case ('@') { a = a.and(#f0.byte).r(4).xor(a.and(#f.byte).l(4)); }
        else {}
    }
    print(a);
}

This might be useful if we need those methods a bit more often.

Paŭlo Ebermann

Posted 2015-09-07T14:10:23.820

Reputation: 1 010

2

STATA, 197 bytes

di _r(a)
gl b=0
forv x=1/`=length("$a")'{
gl c=substr("$a",`x',1)
if"$c"=="!" gl b=255-$b
if"$c"==">" gl b=int($b/2)
if"$c"=="<" gl b=mod($b*2,256)
if"$c"=="@" gl b=mod($b,16)*16+int($b/16)
}
di $b

Ungolfed

display _request(a) //get the input via prompt and put in var a
global b=0 //initialise A to be 0
forv x=1/`=length("$a")'{ //for loop from 1 to last char in a
global c=substr("$a",`x',1) //get the char at index x in a
if "$c"=="!" global b=255-$b //invert is the same as 255-A
if "$c"==">" global b=int($b/2) //right shift is the same as A/2 (with integer division)
if "$c"=="<" global b=mod($b*2,256) //left shift is the same as A*2%256
if "$c"=="@" global b=mod($b,16)*16+int($b/16) //nibble swap is the same as A%16*16+A/16
}
display $b //display the result of A

Does not work with the online interpreter and requires the non-free default interpreter. This would be somewhat easier with actual bitwise operations, but I don't think they're too useful for most of the common uses of STATA.

bmarks

Posted 2015-09-07T14:10:23.820

Reputation: 2 114

Why doesn't the online interpreter work? – CalculatorFeline – 2017-06-21T03:23:00.483

2

Julia, 117 94 86 73 bytes

p->(a=0x0;[a=c==33?~a:c==60?a<<1:c==62?a>>1:c!=64?a:a<<4|a>>4for c=p];1a)

This is an anonymous function that accepts a string and returns an integer. To call it, assign it to a variable.

Ungolfed:

function f(p)
    # Initialize the accumulator to 0 as an 8-bit unsigned integer
    a = 0x0

    # Loop over the characters in the input
    for c in p
        a = c == 33 ? ~ a :        # '!'
            c == 60 ? a << 1 :     # '<'
            c == 62 ? a >> 1 :     # '>'
            c != 64 ? a :          # no-op
            a << 4 | a >> 4        # '@'
    end

    # Convert the accumulator to a regular integer and return
    return Int(a)
end

Saved 8 bytes thanks to Sp3000 and 13 thanks to Dennis!

Alex A.

Posted 2015-09-07T14:10:23.820

Reputation: 23 761

2

JavaScript, 104

[].reduce.call(prompt(),function(a,i){return(i=='!'?~a:i=='>'?a/2:i=='<'?a*2:i=='@'?a>>4|a<<4:a)&255},0)

Nested ternary operators map to instructions.

BITWISE AND is used to constrain our Number type to a single byte.

Andrew Vermie

Posted 2015-09-07T14:10:23.820

Reputation: 121

2

JavaScript (ES6), 76 81

As an unnamed function returning the accumulator value

This is a porting of the super clever answers by @daniero (that have way too few upvotes)

Bonus: you can pass an initial value of the accumulator. If not passed, starting value is 0 as by specific.

(p,a)=>(p.replace(/[!<>@]/g,i=>a=(i<'<'?~a:i<'>'?a*2:i<'@'?a/2:a*257/16)&255),a)

Test running the snippet below in any EcmaScript 6 browser (I tested in Firefox)

f=(p,a)=>[...p].map(c=>a=255&[a,~a,a*2,a/2,a*257/16][1+'!<>@'.indexOf(c)])|a

// TEST
out=x=>O.innerHTML+=x+'\n'

function go(x) { out(x+' -> '+f(x)) }

go('!'),go('!>>'),go('!<@'),go('!nop!&6*!')

// LESS GOLFED
F=(p,a)=>// a as a parameter, if not passed its value starts as undefined, then becomes NaN, but the operators '&' and '~' treat it as 0
  [...p].map(c => // execute following function for each character p
    a = 255 & // any intermediate result is converted to numeric and truncate to a byte          
   // evaluate all possible results (then choose one bases on the current character)
   [a,   // NOP, if unexpected char 'a' remains the same
    ~a,  // tilde == binary not (will give a result wider than a byte)
    a*2, // < shift left is *2 (can give a result wider than a byte) 
    a/2, // > shift right is /2 (can give a non integer result)
    a *257 / 16  // move nibbles around (will give a result wider than a byte)
   ] // array of all results
   [1+'!<>@'.indexOf(c)] // find index to get the correct result
  ) // end map, returns an array in any case
    // eventually a single element array containg a
  | a // return accumulator
Test program:<input id=I><button onclick='go(I.value)'>go</button>
<pre id=O></pre>

edc65

Posted 2015-09-07T14:10:23.820

Reputation: 31 086

1

Perl 6, 96 89 bytes

{my $a=0;$a=(+^*,*+<1,*+>1,{$_+<4+$_+>4},{$_})["!<>@".index($_)//4]($a)%256 for .comb;$a}

Old solution:

{my $a=0;$a=(255-*,*+<1+&255,*+>1,{$_+&15+<4+$_+>4},{$_})["!<>@".index($_)//4]($a)for .comb;$a}

bb94

Posted 2015-09-07T14:10:23.820

Reputation: 1 831

1

C#, 119 bytes

i=>{var a=0;foreach(var c in i){if(c=='!')a=~a;if(c=='>')a>>=1;if(c=='<')a<<=1;if(c=='@')a=a<<4|a>>4;a&=255;}return a;}

Other versions I tried, but need more bytes:

Func<string,int>C=i=>{var a=0;foreach(var c in i){switch(c){case'!':a=~a;break;case'<':a<<=1;break;case'>':a>>=1;break;case'@':a=a<<4|a>>4;break;}a&=255;}return a;};

// This is, despite having the worst score, my personal favourite :D
Func<string,int>D=i=>{var f=new Dictionary<char,Func<int,int>>{{'!',q=>~q},{'<',q=>q<<1},{'>',q=>q>>1},{'@',q=>q<<4|q>>4}};var a=0;foreach(var c in i)if(f.ContainsKey(c))a=f[c](a)&255;return a;};

Stefan

Posted 2015-09-07T14:10:23.820

Reputation: 261

1

Python 2.7.3, 104 bytes

Having code in strings to be evaluated looks pretty dirty, but works :D

a=0
for c in raw_input():a=eval({'!':'~a','<':'a<<1','>':'a>>1','@':'a<<4|a>>4'}.get(c,'a'))&255
print a

Here's the output (and input actually..)

And yes, it's really running on a RaspberryPi :)

Example output

Stefan

Posted 2015-09-07T14:10:23.820

Reputation: 261

1

Forth (gforth), 217

: o over ; : x 0 begin key dup emit swap o 13 = if . exit else o 33 = if invert else o 62 = if 1 rshift else o 60 = if 1 lshift else o 64 = if dup 4 lshift swap 4 rshift or then then then then then nip 255 and again ;

Not as short as I had hoped but oh well. I'm sure this can be golfed further. There doesn't seem to be any alternatives to if/elseif :/

Formatted / ungolfed:

: x
  0 ( accumulator )
  begin
    key dup emit swap ( read char, print it and stash it away )
         over 13 = if . exit ( on newline, print accumulator and return. )
    else over 33 = if invert ( inversion )
    else over 62 = if 1 rshift ( shift 1 right )
    else over 60 = if 1 lshift ( shift 1 left )
    else over 64 = if dup 4 lshift swap 4 rshift or ( swap )
    then then then then then
    nip ( remove read character )
    255 and ( constrain accumulator to 1 byte after each step )
  again
;

2xsaiko

Posted 2015-09-07T14:10:23.820

Reputation: 699

1

Crystal, 139 bytes

def f x
b=0_u8
x.chars.each do|c|
b=case c
when'!'
~b
when'>'
b>>1
when'<'
b<<1
when'@'
b<<4|b>>4
else raise ""
end
end
puts b
end

kirbyfan64sos

Posted 2015-09-07T14:10:23.820

Reputation: 8 730

1

C# 193

void Main(){byte a=0;foreach(var c in Console.ReadLine()){if(c=='!')a=(byte)~a;if(c=='>')a=(byte)(a>>1);if(c=='<')a=(byte)(a<<1);if(c=='@')a=(byte)(((a&240)>>4)|((a&15)<<4));}Console.Write(a);}

Stephan Schinkel

Posted 2015-09-07T14:10:23.820

Reputation: 596

2Don't you need using System; or something like that to access Console.ReadLine and Console.Write without the System. prefix? – Alex A. – 2015-09-07T16:30:37.833

Also it seems to me that you shouldn't have to cast to byte for each operation but I could be wrong. – Alex A. – 2015-09-07T17:22:34.127

1

Lua, 344 char

a=string.rep("0",8)
t=io.read()
f={["!"]=function()local s="";for j=1,8 do s=s..(a:sub(j,j)=="0"and"1"or"0") end;return s end,[">"]=function() return "0"..a:sub(1,7) end,["<"]=function()return a:sub(2,8).."0"end,["@"]=function()return a:sub(5,8)..a:sub(1,4)end}
for i=1,#t do a=(f[t:sub(i,i)]or function()return a end)()end
print(tonumber(a,2))

Inspired by @Beta Decay's use of a string accumulator, seeing as lua has no byte type. Could probably be golfed more by using fewer functions.

Delya Erricson

Posted 2015-09-07T14:10:23.820

Reputation: 81

1

R, 194 bytes

b<-readline();A<-rep(0,8);s<-strsplit(b,"")[[1]];for(r in s){if(r=="!")A<-(A+1)%%2;if(r==">")A<-c(0,A)[1:length(A)];if(r=="<")A<-c(A,0)[-1];if(r=="@")A<-c(A[5:8],A[1:4])};print(sum(A*(2^(7:0))))

ungolfed

b <- readline()
A <- rep(0, 8) 
s <- strsplit(b, "")[[1]]
for (r in s) {
    if (r == "!")
        A <- (A + 1) %% 2
    if (r == ">")
        A <- c(0, A)[1:length(A)]
    if (r == "<")
        A <- c(A, 0)[-1]
    if (r == "@")
        A <- c(A[5:8], A[1:4])
}
print(sum(A*(2^(7:0))))

mawir

Posted 2015-09-07T14:10:23.820

Reputation: 21

All the <- can be replaced by = here, thus reducing the code by 7 bytes. Additionally you might be able to replace the series of if statements by one call to switch (as in A=switch(r,"!"=(A+1)%%2, ...)) – plannapus – 2016-04-20T07:08:49.390

The resulting b=readline();A=rep(0,8);s=strsplit(b,"")[[1]];for(r in s)A=switch(r,"!"=(A+1)%%2,">"=c(0,A)[1:length(A)],"<"=c(A,0)[-1],"@"=c(A[5:8],A[1:4]),A);print(sum(A*(2^(7:0)))) is 167 bytes. – plannapus – 2016-04-20T07:17:02.487

1

RPL, 170.5 bytes

The input should be entered as a string on level 1.

\<< DEC 8 STWS \-> S 
    \<< #0d 1 S SIZE 
        FOR I "!><@" S I DUP SUB POS 1 + { \<< \>> NOT SR SL \<< DUP #16d / SWAP #16d * + \>> } SWAP GET EVAL NEXT \>> 
\>>

Jason

Posted 2015-09-07T14:10:23.820

Reputation: 191

1

K, 57 bytes

It's a start:

0{y+2*x}/(8#0){((~:;{-1_0,x};{1_ x,0};4!;{x})"!><@"?y)x}/

tested using Kona:

  f:0{y+2*x}/(8#0){((~:;{-1_0,x};{1_ x,0};4!;{x})"!><@"?y)x}/
...
  f'("!";"!>>";"!<@";"!nop!&6*!")
255 63 239 255

I might be able to do better in k5, but it's a complex series of tradeoffs- for example, converting binary to decimal is as easy as 2/, but the behavior of ? makes it harder to handle a default case for instruction lookup.

JohnE

Posted 2015-09-07T14:10:23.820

Reputation: 4 632

1

PHP, 189 bytes

<? $c='00000000';foreach(str_split($argv[1])as$a){$a=='!'&&$c=strtr($c,'01','10');$a=='<'&&$c=substr($c.'0',1);$a=='>'&&$c=substr('0'.$c,0,8);$a=='@'&&$c=substr($c.$c,4,8);}echo bindec($c);

It's not that it gonna beat many answers, it's only for practice

Einacio

Posted 2015-09-07T14:10:23.820

Reputation: 436

1

HPPPL, 302 294 bytes

#pragma mode(separator(.,;)integer(d8))EXPORT b()BEGIN print();local p,j,a;a:=#0d;INPUT({{p,[2]}});for j from 1 to dim(p)do c:=p(j);case if c==33 then a:=BITNOT(a)end if c==62 then a:=BITSR(a,1)end if c==60 then a:=BITSL(a,1)end if c==64 then a:=BITSL(a,4)+BITSR(a,4)end end;end;print(a*1);END;

Ungolfed:

// make sure integers are unsigned 8 bit decimal numbers
#pragma mode( separator(.,;) integer(d8) ) 
EXPORT b()
BEGIN
  print();
  local p,j,a;
  a:=#0d;                         // set a to integer value 0
  INPUT({{p,[2]}});               // open input dialog treating input as string ( type [2])
  for j from 1 to dim(p) do
    c:=p(j);
    case
      if c==33 then a:=BITNOT(a) end             // !
      if c==62 then a:=BITSR(a,1) end            // >
      if c==60 then a:=BITSL(a,1) end            // <
      if c==64 then a:=BITSL(a,4)+BITSR(a,4) end // @
    end;
  end;
  print(a*1); // converts to proper output by promoting to non integer format
              // print(a) would result in
              // #239:8d for 239 if the default bit size is not set to 8 bits decimal
              // indicating an 8 bit unsigned decimal integer, or
              // #239d if the default bit size is already set to 8 bits decimal

END;

HPPPL Input command

HPPPL Output to Terminal

This answer ensures that the HP Prime uses unsigned 8 bit integers even if the mode is set to e.g. 64 bits by the user. If the calculator is set up manually to using unsigned 8 bit decimal integers, then the pragma command can be omitted. If the output does not need to follow the format strictly then the a*1 at the end can simply be a. Multiplying the result by 1 just ensures the output does not follow the internal output for integer values. The print command in line 4 can also be omitted if the terminal does not need to be cleared before printing out the result. If passing the program as a string argument is allowed, then the INPUT command can be omitted as well.

This is the shortest version with input and proper output, without the pragma argument (if the calculator is set to Uint8 by default:

243 bytes:

EXPORT b()BEGIN local p,j,a;a:=#0d;INPUT({{p,[2]}});for j from 1 to dim(p)do c:=p(j);case if c=33 then a:=BITNOT(a)end if c=62 then a:=BITSR(a,1)end if c=60 then a:=BITSL(a,1)end if c=64 then a:=BITSL(a,4)+BITSR(a,4)end end;end;print(a*1);END;

M L

Posted 2015-09-07T14:10:23.820

Reputation: 2 865