Программирование с битами и байтами


40

В этом задании вы собираетесь написать переводчика для простого языка, который я составил. Язык основан на одном аккумуляторе A, длина которого составляет ровно один байт. В начале программы A = 0. Это языковые инструкции:

!: Инверсия

Эта инструкция просто инвертирует каждый бит аккумулятора. Каждый ноль становится единым целым и каждый становится нулем. Просто!

>: Сдвиг вправо

Эта инструкция сдвигает каждый бит в A на одно место вправо. Самый левый бит становится нулем, а самый правый бит сбрасывается.

<: Сдвиг влево

Эта инструкция сдвигает каждый бит в A на одно место влево. Самый правый бит становится нулем, а самый левый бит отбрасывается.

@: Поменять местами

Эта инструкция меняет старшие четыре бита А на нижние четыре бита. Например, если A есть 01101010и вы выполняете @, A будет 10100110:

 ____________________
 |                  |
0110 1010    1010 0110
      |_______|

Вот и все инструкции! Просто, правда?

правила

  • Ваша программа должна принять ввод один раз в начале. Это будет строка кода. Это не интерактивный переводчик! Вы можете принять ввод только один раз и не нужно возвращаться к началу, как только эта строка была выполнена.
  • Ваша программа должна оценить указанный вклад. Каждый персонаж, который не упомянут выше, игнорируется.
  • Ваша программа должна затем распечатать окончательное значение аккумулятора в десятичном виде.
  • Применяются обычные правила для действительных языков программирования.
  • Стандартные лазейки запрещены.
  • Это , выигрывает наименьшее количество байтов.

Вот несколько небольших программ для проверки ваших работ. Перед стрелкой - код, после - ожидаемый результат:

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

Наслаждайтесь!


Я предполагаю, ! -> 255что мы будем использовать 8 бит на байт здесь? Вопрос не явный.
Тоби Спейт

3
@TobySpeight Байт по определению составляет 8 бит.
HyperNeutrino

Ответы:


15

Pyth, 36 35 байт

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

Испытательный жгут

Внутреннее представление аккумулятора является целым числом. Это целое число изменяется на 256 на каждой итерации, по желанию. Выполненные операции -G-1,G/2 , G*2и Gпреобразуются в базу 16, обращенные, и преобразуются обратно к основанию 10, где Gнаходится аккумулятор.

Я пропустил линию о игнорировании всего остального. Это было исправлено. Спасибо, @ Денис.


Так -G-1короче чем ~Gв пите? Я несколько сомневаюсь в этом.
CalculatorFeline

Код в вопросе на самом деле t_G, где _есть отрицание и tесть -1. В Pyth ~означает что-то совершенно другое.
Исаак

Я имел в виду Python ~(побитовое НЕ)
CalculatorFeline

@CalculatorFeline Моя точка зрения заключалась в том, что в Pyth нет ни одной символьной функции с таким эффектом, поэтому приведенный выше код (по крайней мере, для этой операции) настолько хорош, насколько это возможно.
Исаак

13

С, 96

Предполагая ASCII (или совместимый) ввод:

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);}

опрятнее:

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);
}

По сути это просто набор вложенных троичных выражений. Я увеличиваю полученное значение getchar()так, что EOF (-1) приводит к нулевому значению, и программа завершается.

(ссылка идеально)


1
Я сам попробовал этот вызов и написал почти такой же код. Btw. ваша программа не сбрасывает бит при смещении вверх (ввод: !<>должен приводить к, 127а не к 255). Либо определите свой aкак char, либо используйте строку a&=255(и используйте %u), чтобы получить правильный эффект. Также вы можете сократить свое отрицание a^255до ~a. a>>4&15тоже короче твоего (a&240)/16.
MarcDefiant

Ах, хорошая мысль. Оказывается, было более эффективно маскировать младшие 8 битов на каждой итерации.
брезгливый оссифраж

1
В этом случае вы даже можете использовать строку формата %uвместо%hhu
MarcDefiant

1
Я только что видел это сейчас, но вы также можете использовать a/16|a*16вместо a/16|(a&15)*16. Несколько битов сверху удаляются &255.
MarcDefiant

1
Небольшое улучшение: a*257/16на один байт меньше, чем a/16|a*16.
Тоби Спейт

11

Python 3, 133 байта

Использует словарь, чтобы восполнить отсутствие синтаксиса переключателя в Python. Подробнее здесь .

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))

Аккумулятор представляет собой строку, которая в конце преобразуется в число 10.

Пример ввода / вывода:

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

Если бы это был настоящий, интерактивный переводчик, это было бы for i in sys.stdin::)
Zizouz212

4
@ Zizouz212 Я думаю, ты имеешь в виду, был ли он интерактивным; это выглядит как настоящий переводчик для меня. ;)
Алекс А.

9

Javascript (ES6), 80 91 90 байт

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

Довольно коротко, как только можно. Определяет анонимную функцию, которая принимает программу в качестве входных данных.

  • Поскольку !, берет x XOR 255, поскольку JS's ~рассмотрел быx 32-битное число.
  • Для <, умножается xна 2 и принимает результат мод 256.
  • Ибо >действительно сдвигает биты x1 бит вправо.
  • Для @этажей x/16и добавляет его x%16*16.

Спасибо @vihan за предложение использовать reduceдля сохранения байта.


Вы можете использовать, <чтобы сохранить около 4 байтов. Использование
Reduce

1
@vihan Вы имеете <в виду вместо ==? Если это так, это не сработает, так как неактивные символы будут неправильно выполнять операцию. Я использовал это в своем предыдущем 80-байтовом решении.
ETHproductions

Разве ES6 не является стандартной стрелкой для PPCG, которую вы должны определить?
MayorMonty

@SpeedyNinja Я не знаю ни одного такого стандарта, но если бы вы могли указать мне на пост о нем, я изменю свой ответ.
ETHproductions

8

CJam, 37 байт

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

Попробуйте онлайн в интерпретаторе CJam .

Как это работает

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#

8

Java (8), 514 483 411 366 359 239 224 229 198 194 187 186 184 182 181 180 177 символов

Вау, это было в гольфе много! Спасибо всем, кто дал мне предложения! Я очень ценю это!

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);}}

Гольф 31 (!) Байт, оптимизируя обмен бит с битовыми операциями, в отличие от длинных Integer.???методов.

Поместите в гольф 72 (!!!!) персонажа, удалив ненужную строку, созданную для обмена кусочками. Гораздо лучше, чем раньше !?

Гольф 45 (!!) символов, удалив использование java.util.Scannerи чтение System.inнепосредственно. Обратите внимание, что теперь, когда лямбда-выражение исчезло, Java 8 больше не требуется! Просто Java 1 подойдет!

Гольф 7 символов, сделав класс (default)(удаленное publicключевое слово), благодаря @bmarks

Гольф 120 (!!!!!!!) символов, превратив все эти длинные Integerоперации класса в бит, переключаясь на 255 - a. Теперь это намного короче!

Гольф 15 (!) Символов путем преобразования сдвигов в умножение и деление, удаление скобок из оператора while и создание aлокальных внутриmain метода.

Ungolfed 9 = (chars из-за проблемы с левым сдвигом, не отбрасывающим самый левый байт. Поэтому я теперь делаю mod (256). Правое смещение сделает результирующее число на один бит короче, чем раньше, поэтому нет необходимости использовать modправый сдвиг. Моя вещь обменивает nibble-swap, поменяет последние 4 бита и второй-последний клев, и and (&)обрежет все остальные биты. Моя программа инверсии не вызывает никаких проблем, если исходное число меньше 256.

Игра в гольф 31 35 символов благодаря @Geobits, преобразующему switchоператоры во множество троичных операторов, а также конвертирующим символы в целые, сокращая литералы.

Golfed 7 символов, удалив ненужные &240в полубайтового свопа ( (a&240)>>4до a>>4и преобразования (a&15)<<4в a<<4&240. Последнее изменение только golfed один символ , хотя.

Гольф 1 символ, удалив ненужные =в a /= 2, потому что a = a /= 2эквивалентно a = a / 2.

Играли в гольф 2 символа, поворачиваясь printlnкprint .

Гольф 2 символа, удалив случайный a=в a=255-a( a=a=255-aэквивалентноa=255-a )

Гольф 1 символ, превращаясь a<<4&240вa%16<<4 .

Гольф 1 символ, добавив скобки за пределами троичного заявления и делать %256. Таким образом, нет %16необходимости в левой части смены мест. В скобках добавлено 2 символа, а в %16сохранении - 3 символа.

Golfed 3 символов путем изменения classк interfaceи удалению с publicпомощью функции методы статического интерфейса Java 8 в. Спасибо @TheNumberOne (без комментариев, но найти его ответ на "Советы по игре в гольф на Яве"


Я не думаю, что класс должен быть публичным. Кроме того, я думаю, что если вы сделаете Integer вместо int, вы можете сделать a.parseInt, a.toString и т. Д. Вместо Integer.parseInt, Integer.toString и т. Д.
bmarks

Спасибо за первое предложение; Я собираюсь удалить все Integerметоды класса, хотя.
HyperNeutrino

Возможно, вы можете сделать while ((i = System.in.read ())> 10) вместо! = 10, чтобы сохранить байт?
Закладки

Хорошая идея, но то, что меньше 10, приведет к завершению программы, и я должен игнорировать другие символы, а не ставить конец света (или, по крайней мере, мою программу :)). возможно, нет действительных символов ascii ниже 10.
HyperNeutrino

4
Это никогда почти никогда не стоит использовать switchто время как игра в гольф. case/ breakПросто слишком долго. Вы должны быть в состоянии сохранить кучу, сделав все это троичным; что-то вродеa=i=='!'?255-a:i==62?a/2:i=='<'?a*2%256:i=='@'?(a&240)>>4|(a&15)<<4:a;
Geobits

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}

Образец прогона:

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
}

Удивительно коротко для Rust. Ничто иное, действительно интересное, кроме того факта, что сегодня я узнал больше правил приоритета - кто знал, (a>>b)|c- это то же самое, что и a>>b|c?

Сбрил байт, изменив n>>=1на n/=2; однако, то же самое не может быть сделано с умножением, потому что арифметическое переполнение - паника (то есть крах) в Rust.


2
Старшинство вещь имеет смысл , когда вы убедите себя , что >>это своего рода походит деления и |является своего рода походит дополнение.
Линн

6

HP 41C / CV / CX (? Байт, 42 шага)

Чисто для хихиканья, вот он для калькулятора HP 41C / CV / CX. (Требуется либо модуль расширенных функций, либо 41CX для функции ATOX.) К сожалению, калькулятор не сообщает размеры программы в байтах.

Поместите вашу программу в регистр Alpha, что немного сложно, так как нет возможности войти! или @ прямо с клавиатуры (используйте XTOA с кодами ASCII 33 и 64 соответственно, чтобы добавить их).

Шаги 08 и 10 позволяют игнорировать недействительные коды операций; удалите их, чтобы сохранить 2 шага, но программа потерпит крах при неверном вводе.

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

6

Python 2, 79 байт

Я понял, что я сделал что-то очень похожее на это в Python ранее. Это просто порт моего ответа на Ruby , но это, кстати, самый короткий ответ Python на данный момент: D

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

Отличие от версии для Ruby состоит в том, что она не игнорирует неверные инструкции при переборе ввода. Вместо этого я использую тот факт, что Python имеет тенденцию возвращаться, -1а не nilпри отсутствии совпадений - текущее значение aдобавляется в конец массива результатов, так что все недопустимые инструкции отображаются на одно и то же неизменное значение.


4

Python 3, 124 94 93 байта

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)

"!" то же самое, что вычитание из 255.
"<" такое же, как умножение на 2. Но 8-битный регистр означает mod 256.
">" такое же, как целочисленное деление на 2.
"@" означает сдвиг последних 4 битов (a%16 ) на 4 бита ( *16) и добавление первых четырех битов ( a/16).

РЕДАКТИРОВАТЬ (читать бесстыдное копирование)
Увидел другой ответ в Python (путем бета-распада). Он использует действительно эффективный способ имитации переключений, используя словарь. Используя это, мы можем написать

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

Спасибо, бета распад.


Независимо от того, какую операцию вы делаете, вы должны уменьшить мод 256правильно? Так почему бы не сделать это в конце a={"!":255-a,"<":a*2,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)%256. Это сразу же экономит вам байт (потому что вы будете делать a*2вместо a<<1) ... но ответ @ daniero также показывает, что если вы сделаете это таким образом, то (a%16)<<4его можно сократить до простого a<<4, потому что любой бит 16 или больше будет исключен после умножения это на 16 и уменьшить его мод 256. Ницца! Кроме того, теперь вы можете заменить 255-aна -1-a... или лучше, просто ~a. В целом, эти предложения должны сэкономить вам 9 байтов.
Матмандан

3

Haskell, 89 байт

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

Пример использования: f "!>>"->63


3

Ржавчина, 111 байт

Больше комментариев к ответу @ Doorknob, но у меня нет ни одного представителя для комментариев, так как я только что создал аккаунт.

Его решение Rust можно сбрить на 10 байт следующим образом:

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}

Я думал, что мы могли бы стать еще короче, используя сложение ( doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold ), но удивительно немного дольше.
user4867444

3

Python 3, 127 байт

Редактировать: коротко, спасибо @Jakube

Edit2: исправить, спасибо @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)

Может быть, это потому, что новая линия Windows. Это плюс два байта. Я буду использовать этот счетчик байтов в следующий раз. :-) Благодарность.
uno20001

Обратите внимание, что это не отбрасывает самый левый бит при сдвиге влево, поэтому !<дает, 510пока это должно быть254
Rohcana

Я надеюсь, что теперь это так. Извините за мои ошибки, это мой первый "гольф" вызов.
uno20001

3

Цейлон, 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);}

отформатирован:

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и #f0шестнадцатеричные числа для клевов, .byteпреобразует целое число в байт. Мне повезло, что .stringатрибут Byte уже использует беззнаковое представление байта. В Цейлоне также есть оператор переключения без провала, а строка представляет собой список символов, который можно повторять.

Я также попытался сократить эти имена методов с длинным сдвигом, используя импорт псевдонимов, но на самом деле это становится на 7 байт длиннее:

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);}

отформатирован:

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);
}

Это может быть полезно, если нам нужны эти методы немного чаще.


3

Рубин, 81 73 байта

Гораздо проще - нет оценки! Для каждого действительного символа на входе он оценивает каждую инструкцию и находит соответствующую инструкцию по индексу $&(текущий символ на входе).

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

1
Это гений. Гораздо короче, чем любой другой способ. 2 отзыва от меня!
edc65

Как ты можешь удвоить голос?
HyperNeutrino

@JamesSmith Он, вероятно, имеет в виду это и мой ответ на Python :)
Даниеро

@danerio я вижу.
HyperNeutrino

2

STATA, 197 байт

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

Не работает с онлайн-переводчиком и требует несвободного переводчика по умолчанию. Это было бы несколько проще с реальными побитовыми операциями, но я не думаю, что они слишком полезны для большинства распространенных применений STATA.


Почему не работает онлайн переводчик?
CalculatorFeline

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)

Вложенные троичные операторы отображаются в инструкции.

BITWISE AND используется для ограничения нашего типа Number одним байтом.


2

Юлия, 117 94 86 73 байта

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)

Это анонимная функция, которая принимает строку и возвращает целое число. Чтобы вызвать его, присвойте его переменной.

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

Сохранено 8 байтов благодаря Sp3000 и 13 благодаря Деннису!


2

JavaScript (ES6), 76 81

В качестве неназванной функции, возвращающей значение аккумулятора

Это портирование супер-умных ответов @daniero (у которых слишком мало голосов)

Бонус: вы можете передать начальное значение аккумулятора. Если не передано, начальное значение равно 0, как определено.

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

Попробуйте запустить приведенный ниже фрагмент в любом браузере EcmaScript 6 (я тестировал в 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>


1

Crystal, 139 байтов

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

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);}

2
Вам не нужно using System;или что-то подобное для доступа Console.ReadLineи Console.Writeбез System.префикса?
Алекс А.

Также мне кажется, что вам не нужно byteприводить для каждой операции, но я могу ошибаться.
Алекс А.

1

Луа, 344 чар

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))

Вдохновленный @Beta Decay использованием строкового аккумулятора, поскольку lua не имеет байтового типа. Вероятно, можно больше играть в гольф, используя меньше функций.


1

R 194 байта

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))))

Здесь <-можно заменить все =, уменьшив код на 7 байт. Кроме того, вы можете заменить серию ifутверждений одним вызовом switch(как в A=switch(r,"!"=(A+1)%%2, ...))
plannapus

В результате 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))))получается 167 байтов.
plannapus

1

RPL, 170,5 байта

Ввод должен быть введен в виде строки на уровне 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 \>> 
\>>

1

К, 57 байт

Это начало:

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

протестировано с использованием 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

Я мог бы добиться большего успеха в k5, но это сложная серия компромиссов - например, преобразование двоичного в десятичное так же просто, как и то 2/, но поведение ?усложняет обработку случая по умолчанию для поиска команд.


1

PHP, 189 байт

<? $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);

Дело не в том, что он побьет много ответов, это только для практики


1

HPPPL , 302 294 байта

#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

Выход HPPPL на терминал

Этот ответ гарантирует, что HP Prime использует 8-разрядные целые числа без знака, даже если пользователь установил режим, например, 64-разрядный. Если калькулятор настроен вручную на использование 8-разрядных целых чисел без знака, то эту pragmaкоманду можно опустить. Если вывод не должен строго следовать формату, то a*1в конце может быть просто a. Умножение результата на 1 просто гарантирует, что вывод не будет следовать за внутренним выводом для целочисленных значений. Команда printв строке 4 также может быть опущена, если нет необходимости очищать терминал перед распечаткой результата. Если передача программы в качестве строкового аргумента разрешена, тоINPUT команда также может быть опущена.

Это самая короткая версия с вводом и правильным выводом без аргумента прагмы (если калькулятор по умолчанию установлен в Uint8:

243 байта:

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;

1

Perl 6, 96 89 байт

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

Старое решение:

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

1

C #, 119 байт

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;}

Другие версии, которые я пробовал, но нужно больше байтов:

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;};

1

Python 2.7.3, 104 байта

Наличие кода в строках для оценки выглядит довольно грязно, но работает: 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

Вот вывод (и ввод на самом деле ..)

И да, он действительно работает на RaspberryPi :)

Пример вывода

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.