Big or Little Endian


57

Напишите программу или функцию, которая выводит Lif, если она работает на архитектуре с прямым порядком байтов или Bif, если она запускается на архитектуре с прямым порядком байтов. Вывод в нижнем регистре lили bтакже приемлемо.

Там нет ввода.

Подсчет очков - это код гольф, поэтому выигрывает код с наименьшим количеством байтов.

Изменить: Согласно комментариям ниже, я уточняю, что запись должна быть в состоянии работать на любой архитектуре.

Я считаю, что это влияет только на один ответ, и этот ответ ясно показал, что это так.


1
Память о коробке. Я не уверен, что вы имеете в виду
Лиам

7
Я думаю, что это интересный вызов (и это выход из нормы), но его будет чрезвычайно сложно проверить. Тем более, что большая часть кода будет очень специфичной для платформы.
DJMcMayhem

7
Да, я думаю, что это будет интересно, потому что, надеюсь, что с языками esolangs и golfing сложнее, чем с «нормальными» языками. У меня такое чувство, что их не так сложно проверить. В худшем случае они должны быть проверены вручную
Лиам

2
Я думаю, что ответ на основе конкретного машинного кода запрещено? В противном случае B0 4C C3, который является mov al, 'L' / retили unsigned char f(){ return 'L'; }, будет правильным ответом x86.
Маргарет Блум

5
Браво! для соревнования по коду, в котором языки программирования общего назначения могут быть конкурентоспособными.
PellMell

Ответы:


42

Python, 33 байта

import sys
exit(sys.byteorder[0])

sys.byteorderлибо либо, 'little'либо 'big'(и для тех из вас, кто прочтет это предложение, не глядя на код, [0]означает взять первый символ).


Задача говорит, что вывод должен быть Lи B(или вариант в нижнем регистре), а не все слово.
user2428118

43
Вот почему он говорит sys.byteorder[0], то есть первый символ byteorder.
s3lph

36

C, 26 байтов

a=66<<24|76;f(){puts(&a);}

Предполагает 32-битные intи ASCII символы. Проверено на amd64 (little-endian) и mips (big-endian).

GCC, 23 байта

00000000: 613d 2742 0000 4c27 3b66 2829 7b70 7574  a='B..L';f(){put
00000010: 7328 2661 293b 7d                        s(&a);}

Предложено feersum. Значение многосимвольных констант зависит от реализации, но, похоже, это работает в GCC. Проверено на одинаковых архитектурах.


7
Короче a='B\0\0L';В \0s можно заменить байты нуля.
feersum

1
@feersum Порядковый номер многосимвольных констант зависит от реализации. Обычно я бы не беспокоился об этом в кодовом гольфе, но эта проблема заключается в различении реализаций.
Андерс Касеорг

Этот код в настоящее время работает не в GCC?
feersum

1
@feersum C89 позволяет оба.
Андерс Касеорг

1
Используя xlc (VisualAge C ++ Professional / C для компилятора AIX, версия 6) на RS6000, работающем под AIX 5.2, 26-байтовая программа успешно печатает «B»
Джерри Иеремия,


20

JavaScript ES6, 50 байт

_=>"BL"[new Int8Array(Int16Array.of(1).buffer)[0]]

Я не знаю, кто решил, что для объектов TypedArray было бы неплохо раскрыть нативную последовательность интерпретатора, но мы здесь.


5
Люди из WebGL думали, что это хорошая идея - избегать преобразования порядка байтов при переходе на GPU.
Почти

11

C, 36 35 байтов

1 байт благодаря @algmyr и @owacoder.

main(a){printf(*(char*)&a?"L":"B");}
main(a){putchar(66+10**(char*)&a);}
main(a){putchar("BL"[*(char*)&a]);}

Кредиты здесь .

Не проверено, поскольку у меня нет машины с прямым порядком байтов.


2
Разрешает ли спецификация C функцию с одним аргументом main?
CodesInChaos

@codesinchaos да, это так. Это будет количество аргументов командной строки. Обычно здесь используется инициализация переменной, 1потому что ввод не дается (а имя программы всегда считается первым аргументом)
Лиам

2
@Liam: Если разрешено что-либо кроме 0 или 2, реализация определяется в C11.

1
Или main(a){putchar("BL"[*(char*)&a]);}.
owacoder

2
Если вы запутались с конвенцией вызовов снижается до 31: main(char a){putchar("BL"[a]);}.
Андреа Биондо

8

Математика, 22

{B,L}[[$ByteOrdering]]

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


1
Встроенные модули хороши (большинство ответов используют их тоже)
Лиам

2
И еще раз, Mathematica имеет встроенный!
gcampbell

3
Я думаю, что это фрагмент, а не программа или функция, и вы должны добавить, &чтобы сделать его функцией. (Но могут быть разногласия по поводу того, что составляет «программу».)
Андерс Касеорг,

1
@ Андерс Я не очень знаком с текущими стандартами для PCG (если я когда-либо был), но ИМХО одним из преимуществ интерпретируемого языка является то, что фрагмент кода - это программа. Это может быть выполнено автономно так же, как любая другая программа в Mathematica .
Мистер Волшебник

1
@ Mr.Wizard Обратите внимание, что «программа» в Mathematica относится к автономному сценарию (который требует явной печати), тогда как в этом ответе используется REPL.
LegionMammal978

8

С, 27

На один байт длиннее, но здесь все равно:

f(){putchar(htons(19522));}

Это работало нормально, не могли бы вы объяснить это мне.
ABcDexter

3
@ABcDexter двоичное расширение 19522 - это 1001100 01000010(пробел для разделения байтов). Теперь, если вы возьмете каждый байт, вернетесь к основанию 10 и проверите таблицу ASCII, вы увидите, что эта последовательность байтов эквивалентна LB. htonsбудет делать свое дело , и putcharбудет печатать только LSB. В системах с прямым порядком байтов, то есть Bв порядке с прямым порядком байтов, htonsбудут переброшены байты, поэтому LSB есть L.
Кролтан

Замените 19522на 'LB'for для предупреждений компилятора и -1 байт.
Стэн Струм

8

Машинный код PowerPC - 20 байт

PowerPC имеет двоичный код (порядок байтов может быть установлен при запуске), поэтому этот код должен соответствовать требованию вызова для возможности запуска на машинах BE и LE. Это функция, которая возвращает 1 'L' или 'B'зависит от установленного в настоящий момент порядка байтов.

В качестве функции AFAICT он соответствует SVR4 PowerPC ABI (используется Linux на ppc32), PowerOpen ABI (используется, например, AIX) и OS X ABI. В частности, он опирается только на тот факт, что GPR 0 является энергозависимым чистым регистром, а GPR 3 используется для возврата «маленьких» значений.

00000000 <get_endian>:
   0:   7c 00 00 a6     mfmsr   r0
   4:   54 03 0f fe     rlwinm  r3,r0,1,31,31
   8:   1c 63 00 0a     mulli   r3,r3,10
   c:   38 63 00 42     addi    r3,r3,66
  10:   4e 80 00 20     blr

Теперь это выглядит так:

  • MSR считывается в регистр GP 0; MSR содержит в бите 31 установки порядка байтов (0 = старший порядок; 1 = младший порядок);
  • rlwinmЭкстракты только , что бит: оно принимает значение в GPR0, г otates л EFT на 1 место (так что теперь находится в положении 0) и м запрашивает его с 1 (маской , получаемой от этого 31,31 2 ); результат заносится в регистр ГП 3;
  • умножьте результат на 10 и сумму 66 ( 'B') (10 - разница между 'L'и 'B')
  • наконец, вернитесь к абоненту

Примечания

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

    2018 Обновления : Raymond Chen публикует серию об архитектуре PowerPC, вы можете найти здесь свое большое сообщение о rlwinm& друзьям.


7

Java 8, 96, 64 52 байта

()->(""+java.nio.ByteOrder.nativeOrder()).charAt(0);

Гольф на основе этого ответа . Вся заслуга принадлежит @LeakyNun и @AlanTuning. Ява продолжает проигрывать.

96 байт:

 char e(){return java.nio.ByteOrder.nativeOrder().equals(java.nio.ByteOrder.BIG_ENDIAN)?'b':'l';}

64 байта:

char e(){return(""+java.nio.ByteOrder.nativeOrder()).charAt(0);}

Непроверенный б / у У меня нет доступа к машине с прямым порядком байтов.


1
char e(){return(""+java.nio.ByteOrder.nativeOrder()).charAt(0);}
Утренняя монахиня

char e(){return(""+java.nio.Bits.byteOrder()).charAt(0);}
Утренняя монахиня

@LeakyNun Я не вижу биты в Java API, и когда я запускаю его, он выдает мне: «Биты не доступны в java.nio»
Blue

Ох, тогда ладно.
Утренняя монахиня

52 байта, если вы используете лямбду! ()->(""+java.nio.ByteOrder.nativeOrder()).charAt(0);
Шон Уайлд,

6

Perl, 38 36 байт

say+(pack"L",1 eq pack"V",1)?"L":"B"

Работает, упаковывая число в порядке байтов системы по умолчанию и сравнивая его с числом, упакованным в порядке байтов с прямым порядком байтов.


6

(G) Далее, 24 байта

here $4200004C , c@ emit

Предполагается, что ячейки 32-битные (и что ваш интерпретатор Forth поддерживает базовые префиксы Gforth ). Он просто сохраняет число 0x4200004C в памяти, а затем отображает байт в нижнем конце.


5

C, 34 байта

Это предполагает кодировку символов ASCII

main(a){putchar(66+10**(char*)a);}

Звони без аргументов.

Объяснение:

При вызове aбудет 1. *(char*)aДоступ к первому байту a, который на платформах с прямым порядком байтов будет равен 1, на платформах с прямым порядком байтов будет 0.

Таким образом, на платформах с прямым порядком байтов этот код будет передавать 66 + 10 * 0 = 66 putchar. 66 - это код ASCII для B. На платформах с прямым порядком байтов он пройдет 66 + 10 * 1 = 76, что является кодом ASCII L.


5

C #, 60 52 байта

C # на удивление конкурентоспособен в этом.

char e=>System.BitConverter.IsLittleEndian?'L':'B';

Кредиты Groo для синтаксиса C # 6.

60 байтов:

char e(){return System.BitConverter.IsLittleEndian?'L':'B';}

С синтаксисом C # 6 вы можете немного его укоротить: char e=>System.BitConverter.IsLittleEndian?'L':'B';конечно, это (как и ответ Java) на самом деле не печатает значение.
Groo

Добро пожаловать в Программирование Пазлов и Code Golf! Это хороший первый ответ.
Алекс А.

5

Юлия, 24 19 байт

()->ntoh(5)>>55+'B'

Это анонимная функция, которая не принимает никаких данных и возвращает a Char. Чтобы вызвать его, назначьте его переменной. Предполагается, что целые числа являются 64-битными.

ntohФункция преобразует байтов в значение , переданное в него из сетевого порядка байт (большой байтов) к используемому хост - компьютером. На машинах с прямым порядком байтов ntohэто функция идентификации, поскольку преобразование не требуется. На маленьких байтовых машинах байты меняются местами ntoh(5) == 360287970189639680. Что также, возможно, более читабельно, равно: 0000010100000000000000000000000000000000000000000000000000000000в двоичном.

Если мы сместим правильный результат ntoh(5)на 55, мы получим 0 на машинах с прямым порядком байтов и 10 на машинах с прямым порядком байтов. Добавив это к символьной константе 'B', мы получим 'B'или 'L'для больших или маленьких порядковых машин соответственно.

5 байтов сэкономлено благодаря FryAmTheEggman и Деннису!


Для 32-битного вы должны были бы изменить 55 на 23 (также 5 в 16-битном должно было быть 7, моя ошибка). Я думаю , что Деннис имел в виду что - то вроде: ()->ntoh(5)>>55+'B'?
FryAmTheEggman

1
f()='L'-ntoh(10)%16и f()='L'-ntoh(10)&10должен работать на всех платформах.
Деннис


5

Common Lisp, 27 байт

Проверено на SBCL и ECL. Для портативного подхода следует использовать тривиальные особенности .

(lambda()'L #+big-endian'B)

#+Обозначения являются условием для чтения времени , который считывает следующую форму , только если условное выражение истины. Здесь условие представляет собой весь #+big-endianтекст, который означает, что тест выполняется, если :big-endianключевое слово принадлежит *FEATURES*списку (список, который содержит, помимо прочего, информацию, относящуюся к платформе). Следующее выражение 'B, которое либо читается, либо пропускается в зависимости от результата теста. Если ваша платформа имеет формат с прямым порядком байтов и вы пишете приведенную выше форму в REPL, это точно так же, как если бы вы написали следующее:

CL-USER>(lambda()'L 'B)

(NB. CL-USER>Является подсказкой)

Тело функции является неявным PROGN, что означает, что возвращается только оценка последнего выражения. Таким образом , на самом деле выше символ возврата B. Однако, если условие времени чтения оценивается как ложное, форма читается так, как будто вы написали:

CL-USER>(lambda()'L)

... который просто возвращает символ L.


Отрывки не допускаются; Напишите полные программы или функции вместо.
Эрик Outgolfer

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Обновлено, спасибо
coredump

Примечание. Фрагменты кода разрешены только в том случае, если они явно разрешены OP.
Эрик Outgolfer

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Не могли бы вы дать ссылку на это? Здесь есть другие ответы REPL и / или фрагменты оболочки, и в этом мета-посте можно предположить, что ответы REPL могут быть в порядке по умолчанию. Благодарю.
coredump

5

ARMv6 и более поздние: машинный код 20 байтов

0xE10F1000 : MRS   r0,CPSR        ; read current status register
0xE3110C02 : TST   r0,#1<<9       ; set Z flag if bit 9 set
0x03A0004C : MOVEQ r0,#'L'        ; return 'L' if Z clear
0x13A00042 : MOVNE r0,#'B'        ; return 'B' if Z set
0xEBxxxxxx : BL    putchar        ; print it (relative branch)

Непроверенный, поскольку у меня нет подходящей машины в руки. Бит 9 CPSR дает текущий порядок загрузки / сохранения.


Вы можете использовать возврат из функции ( BX lrне так ли?) Вместо putchar, потому что r0это правильный регистр для возвращаемого результата.
Анатолий

Действительно, это (на самом деле MOV pc, lr) было в одном из моих предыдущих правок. Однако это соответствует спецификации, чтобы напечатать письмо, а не просто вернуть его.
user1908704

Возможно, я неправильно читаю ссылку, но думаю, что это можно сделать в кодировке инструкции «thumb 2». Это означало бы, что первая команда оставалась 32-битной («кодирование T1» на странице F7-2720 справочного руководства ARM v8, что сделало бы ее 0xF3EF_8000); второй также 32-битный (кодирование операнда немного странно, но может быть сделано с «i: imm3», установленным в 0010 и «imm8» в 00000010, что дает общую инструкцию 0xF010_2F02). Перед третьей инструкцией нам нужно вставить «ITE EQ» (0xBF0C), чтобы управлять условиями следующих двух инструкций MOV, которые становятся 0x204C и ...
Jules

... 0x2042 (экономия всего 2 байта). Тогда окончательную инструкцию BL немного сложно представить, потому что биты адреса, который мы не знаем, в конечном итоге разбросаны по битам инструкции, которую мы знаем, но это также 32-битное кодирование, поэтому результат будет всего 18 байтов (F3 EF 80 00 F0 10 2F 02 BF 0C 20 4C 20 42 F? ?? ?? ??). Я считаю, что это меняет архитектуру на ARMv8 и более поздние, хотя это может работать в ARMv7 (?).
Жюль

4

Perl 5, 21 + 1 = 22 байта

Беги с perl -E.

say ord pack(S,1)?L:B

Проверено на amd64 (little-endian) и mips (big-endian).


Является ли -Eфлаг действительно необходимо в счетчику байтов? Можно просто сказать, что вы используете Perl 5.10 (поскольку sayкоманда доступна в этой версии)
Пол Пикард,

1
@PaulPicard Но use 5.10.0;это еще много байтов!
Андерс Касеорг

1
@PaulPicard Ваша точка зрения не так. Perl 5.10 требует -Eпереключения или useоператора для say.
Андерс Касеорг

3
-Eявляется "бесплатным" на PPCG. Не нужно ничего добавлять.
Ven

1
(впрочем -nи -pнет)
Ven

4

R, 28 23 байта

substr(.Platform$endian,1,1)

.Platform$endianвозвращает, bigесли работает на старшем порядке и littleесли на маленьком. Здесь, используя substr, он возвращает первую букву вывода, так что либо bили l.

Поскольку endianэто единственный объект, начинающийся с eсодержащегося в объекте, .Platformмы можем уменьшить его благодаря частичному сопоставлению со следующим 23-байтовым кодом:

substr(.Platform$e,1,1)

3

Clojure, 46 44 байта

#(nth(str(java.nio.ByteOrder/nativeOrder))0)

Это функция, которая использует встроенную функцию Java для получения порядкового номера машины. Затем получите его строковое представление, которое будет либо, "LITTLE_ENDIAN"либо, "BIG_ENDIAN"и получите первый символ любой выбранной строки и верните ее.

Сохранено 2 байта благодаря @ cliffroot .


Что такое clojure на самом деле, это лисп или ява?
Утренняя монахиня

@LeakyNun Может быть практический LISP, который работает с Java? Сложно сказать.
миль

#(nth(str(java.nio.ByteOrder/nativeOrder))0)на 2 байта короче
обломок

3

Рубин, 3130 символов

puts [1].pack("s")>"\01"??L:?B

Хм, должно быть, лучше. Считайте на 5 символов меньше, если символ не нужно выводить, так как я думаю, что другие решения не включают печать. то есть удалите часть «вводит», если вы не хотите, чтобы что-то печаталось.


Если я правильно помню, после Ruby 1.9 можно использовать ?Lи ?Bвместо puts :Lиputs "B"
Sherlock9

Я думаю, что puts [76,66].pack("s")[0]будет работать.
Уэйн Конрад

@ Sherlock9, спасибо, на один символ меньше. @WayneConrad, возможно, добавьте свой ответ, у меня нет под рукой машины с прямым порядком байтов для тестирования, но на младшем уровне это работает. Но изменение, как это не работает puts [76,66].pack("s>")[0]. Это означает, что возможно не работать с прямым порядком байтов по какой-то причине, которую я плохо понимаю. Но этот, кажется, работает (получено из вашего решения) puts [19522].pack("s>")[0]. WDYT? Интересно, смогу ли я найти место для оценки с прямым порядком байтов?
Акостадинов

Увы, мне также не хватает машины с прямым порядком байтов для тестирования.
Уэйн Конрад

3

Bash (и другие оболочки Unix), 32 (33) байта

Первая и вторая попытка:

case `echo|od` in *5*)echo B;;*)echo L;;esac # portable
[[ `echo|od` =~ 5 ]]&&echo B||echo L         # non-portable

Спасибо Деннису, более короткая версия:

od<<<a|grep -q 5&&echo L||echo B  # non-portable
echo|od|grep -q 5&&echo B||echo L # portable

echoУтилита выводит символ новой строки, с шестнадцатеричным значением 0A, и никакого другого выводом. Ибо <<<aэто так 61 0A.

По odумолчанию утилита интерпретирует входные данные как двухбайтовые слова, дополненные нулями, если число байтов нечетное, и преобразует их в восьмеричное. Это приводит к тому, что выходные данные echo интерпретируются как 0A 00, которые преобразуются в значения 005000с прямым порядком байтов или 000012с прямым порядком байтов. 61 0Aстановится 005141в порядке байтов и 060412в порядке байтов. Полный выход ода также включает в себя адрес и размер данных означает , что мы не можем использовать 0, 1или 2для испытания.

Команда четко определена, чтобы раскрыть системный порядок. Из стандарта :

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

Примечания по совместимости

Я не уверен, что использование echo|odобратных кавычек без двойных кавычек [что приводит к аргументу из трех слов в case] поддерживается во всех системах. Я не уверен, что все системы поддерживают сценарии оболочки без завершающей строки. Я в основном уверен, но не на 100% в поведении od с добавлением байта заполнения в системах с прямым порядком байтов. При необходимости echo aможет использоваться для портативных версий. Все скрипты работают в bash, ksh и zsh, а переносимые - в dash.


Ни одно из изменений не является необходимым; просто поместите одну оболочку, в которой он работает, в языковой хедет, и все готово.
Деннис

1
@Dennis Мне нравится делать что такой анализ ... хотя это более интересно , если я делать найти что - то нестандартное , который получает более короткий ответ на баш или Zsh , чем другие. Может быть, я посмотрю, что можно сделать[[
Random832

1
Ничего плохого в анализе. Последний абзац звучал так, словно вы были неуверены в правильности ответа на конкретную оболочку ... он od<<<a|grep -q 5&&echo L||echo Bдолжен работать в Bash и других.
Деннис

Я проверил его на виртуальной машине с прямым порядком байтов и echo|odпечатал, 0000000\n005000\n0000001как вы ожидали.
Деннис

@ user17752 Потому что порядок байтов не влияет на вывод od -a.
Random832

3

PHP, 16 байт

<?=pack(S,14)^B;

Здесь используются два трюка, которые не используются в двух существующих ответах PHP:

  1. Значение, переданное pack () или unpack (), может быть любым, а не 0 или 1.
  2. Побитовый оператор XOR ( ^) работает со строками, и в результате получается длина до более короткой строки, избегая необходимости индексации строки или троичного оператора.

2

Узел, 42 байта

n=>require('os').endianness()[0]

Pro: есть встроенный Con: имена свойств очень длинные


2

PowerShell, 44 байта

[char](66+10*[BitConverter]::IsLittleEndian)

Характер 66 Bи 10 символов позже это число 76, L. Логическое значение «true» становится 1при приведении к числу. BitConverterэто стандартный класс .NET.


1

Ракетка, 35 28 байт

(if(system-big-endian?)'B'L)

'Bили 'Lсоответственно. Дайте мне знать, если это не достаточно конкретно :)



1

Haskell (используя числовые типы с ограниченным размером только GHC), 75 байтов

import Unsafe.Coerce
import GHC.Int
f="BL"!!fromEnum(unsafeCoerce 1::Int8)

(не тестируется на архитектуре с прямым порядком байтов, но похоже, что она должна работать!)


1

К, 15 байт

    ("bl")@*6h$-8!`
    ,"l"

Объяснение;

    From right to left;
    -8!`       /serialises the back tick and returns (0x010000000a000000f500)
    6h$-8!`    /This casts the result to `int which is type 6h(could have used `int$-8!`) - the result is (1 0 0 0 10 0 0 0 245 0i)
    *6h$-8!`   /* means first, we take the first item which is 1. Since it will be either 1 or 0, we can use it to index (@) into the two element list on the left i.e. ("bl")1 returns "l" and ("bl")0 returns b

1

Баш, 27 байт

iconv -tucs2<<<䉌|head -c1

( U + 424C ) кодируется в виде трех UTF-8 байт: E4 89 8C.

Предполагается, что iconvиспользуется функция из glibc и используется локаль UTF-8.

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