Grande ou pequeno Endian


57

Escreva um programa ou função que produza um Lif executado em uma pequena arquitetura endian ou um Bif executado em uma arquitetura big endian. Saída em minúsculas lou btambém é aceitável.

Não há entrada.

A pontuação é código de golfe, portanto o código com o menor número de bytes vence.

Editar: conforme os comentários abaixo, estou esclarecendo que a entrada deve ser capaz de executar em qualquer arquitetura.

Eu acredito que há apenas uma resposta que isso afeta, e essa resposta indicou claramente que esse é o caso.


11
A memória da caixa. Eu não tenho certeza do que você quer dizer
Liam

7
Eu acho que esse é um desafio interessante (e está fora do padrão), mas será extremamente difícil testá-lo. Especialmente porque a maior parte do código acabará sendo extremamente específica da plataforma.
DJMcMayhem

7
Sim, acho que será interessante, porque espero que seja algo que os esolangs e os idiomas do golfe tenham mais dificuldade do que os idiomas 'normais'. Tenho a sensação de que eles não serão tão difíceis de verificar. Pior caso, devem ser verificáveis por mão
Liam

2
Eu acho que uma resposta baseada em um código de máquina específico é proibida? Caso contrário B0 4C C3, qual é mov al, 'L' / retou unsigned char f(){ return 'L'; }seria uma resposta x86 válida.
Margaret Bloom

5
Bravo! para um desafio de golfe de código no qual linguagens de programação de uso geral podem ser competitivas.
PellMell

Respostas:


42

Python, 33 bytes

import sys
exit(sys.byteorder[0])

sys.byteorderé um 'little'ou ou 'big'(e para aqueles de vocês que lerão esta frase sem olhar o código, [0]significa assumir o primeiro caractere).


O desafio diz que a saída deve ser Le B(ou a variante minúscula), não a palavra inteira.
user2428118

43
É por isso que diz sys.byteorder[0], ou seja, o primeiro caractere de byteorder.
S3lph

36

C, 26 bytes

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

Assume caracteres de 32 bits inte ASCII. Testado em amd64 (little-endian) e mips (big-endian).

GCC, 23 bytes

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

Sugerido por feersum. O valor das constantes com vários caracteres depende da implementação, mas isso parece funcionar no GCC. Testado nas mesmas arquiteturas.


7
Menor é a='B\0\0L';O \0s pode ser substituído por bytes nulos.
feersum

11
@feersum O endianness de constantes com vários caracteres parece ser dependente da implementação. Normalmente, eu não me preocuparia tanto com isso no código golf, mas esse desafio é sobre distinguir entre implementações.
Anders Kaseorg

Atualmente, esse código funciona em algo diferente do GCC?
feersum 28/07

11
@feersum C89 permite ambos.
Anders Kaseorg

11
Usando xlc (VisualAge C ++ Professional / C para AIX Compiler, versão 6) em um RS6000 executando o AIX 5.2 do programa de 26 byte imprime com sucesso "B"
Jerry Jeremias

24

MATLAB / oitava, 24 bytes

[~,~,e]=computer;disp(e)

A computerfunção fornece informações sobre o computador em que está sendo executado. A terceira saída é endianness: Lou Bpara little ou big-endian, respectivamente.

Experimente em Ideone .


11
o que. Isso é algo para o stackoverflow, eu não sabia disso!
Brain Guider

20

JavaScript ES6, 50 bytes

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

Não sei quem decidiu que era uma boa ideia os objetos TypedArray exporem o endianness nativo do intérprete, mas aqui estamos.


5
O pessoal do WebGL achou que era uma boa ideia evitar ter de converter endianness ao passar para a GPU. Quase todo mundo achou estúpido… :(
gsnedders

11

C, 36 35 bytes

1 byte graças a @algmyr e @owacoder.

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

Créditos aqui .

Não testado, pois não tenho uma máquina big-endian.


2
A especificação C permite uma mainfunção de um argumento ?
CodesInChaos

@codesinchaos sim, sim. Será o número de argumentos da linha de comando fornecidos. Normalmente, aqui ele é usado para ter uma variável iniciada para 1porque nenhuma entrada é dada (e o nome do programa sempre conta como o primeiro argumento)
Liam

2
@ Liam: Se algo diferente de 0 ou 2 for permitido, a implementação é definida em C11.

11
Or main(a){putchar("BL"[*(char*)&a]);}.
Owacoder 28/07

2
Se você mexer com a convenção de chamada que vai até 31: main(char a){putchar("BL"[a]);}.
Andrea Biondo 29/07

8

Mathematica, 22

{B,L}[[$ByteOrdering]]

Isso provavelmente quebra alguma regra sobre o não uso de uma função interna, mas não estou realmente interessado em usar o rube goldberging como alternativa.


11
Built-ins são muito bem (a maioria das respostas estão usando-os também)
Liam

2
E mais uma vez, o Mathematica possui um built-in!
Gcampbell 28/07/16

3
Eu acho que esse é um trecho, não um programa ou função, e você deve adicionar &para torná-lo uma função. (Mas pode haver desacordo sobre o que constitui um “programa”.)
Anders Kaseorg

11
@ Anders Eu não estou realmente familiarizado com os padrões atuais para PCG (se alguma vez eu fui), mas IMHO uma vantagem de uma linguagem interpretada é que um trecho é um programa. Isso pode ser executado de maneira independente, como qualquer outro programa no Mathematica .
Mr.Wizard

11
@ Mr.Wizard Observe que um "programa" no Mathematica se refere a um script independente (que requer impressão explícita), enquanto que esta resposta usa o REPL.
LegionMammal978

8

C, 27

Um byte a mais, mas aqui está assim mesmo:

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

Funcionou bem, você pode me explicar.
ABCDexter

3
@ABcDexter é a expansão binária de 19522 1001100 01000010(espaço para separar bytes). Agora, se você pegar cada byte, converter novamente para a base 10 e verificar a tabela ASCII, verá que essa sequência de bytes é equivalente a LB. htonsfará o queputchar quiser e imprimirá apenas o LSB. Nos sistemas big-endian, isto é B, no little-endian, htonsterão invertido os bytes, assim é o LSB L.
Kroltan

Substituir 19522com 'LB'para avisos do compilador e byte -1.
Stan Strum

8

Código da máquina PowerPC - 20 bytes

O PowerPC é bi-endian (o endianness pode ser configurado na inicialização), portanto, esse código deve estar em conformidade com a solicitação de desafio de poder executar as máquinas BE e LE. Esta é uma função que retorna 1 'L' ou 'B'depende da endianness atualmente definida.

Como função, o AFAICT está em conformidade com o SVR4 PowerPC ABI (usado pelo Linux no ppc32), o PowerOpen ABI (usado, por exemplo, pelo AIX) e o OS X ABI. Em particular, ele se baseia apenas no fato de que o GPR 0 é um registro temporário volátil e o GPR 3 é usado para retornar valores "pequenos".

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

Agora, é assim:

  • o MSR é lido no registro GP 0; o MSR contém no bit 31 as configurações de endianness (0 = big endian; 1 = little endian);
  • rlwinmextractos apenas um pouco: leva o valor em GPR0, r Otates l eft por um lugar (de modo que agora está na posição 0) e m pede-o com um (a máscara geradas por aqueles 31,31 2 ); o resultado é colocado no registro GP 3;
  • multiplique o resultado por 10 e some 66 ( 'B') (10 é a diferença entre 'L'e 'B')
  • finalmente, retorne ao chamador

Notas

  1. Sim, a pergunta pede para imprimir , mas não está claro como eu deveria imprimir as coisas no assembly que devem ser executadas sem modificação em diferentes sistemas operacionais. =)
  2. para os interessados, consulte a documentação do rlwinm ; sabendo quase nada sobre o PowerPC, achei este tipo de instruções extremamente interessante.

    Atualização de 2018 : Raymond Chen está publicando uma série sobre a arquitetura PowerPC, você pode encontrar aqui seu ótimo post sobre rlwinm& friends.


7

Java 8, 96, 64 52 bytes

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

Um golfe com base nesta resposta SO . Todo o crédito vai para @LeakyNun e @AlanTuning. Java mantém a sequência de perdas.

96 bytes:

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

64 bytes:

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

Não testado b / c Não tenho acesso a uma máquina big-endian.


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

char e(){return(""+java.nio.Bits.byteOrder()).charAt(0);}
Freira vazando

@LeakyNun Não vejo Bits na API Java, e quando eu executá-lo dá-me "Bits não é público em java.nio"
Azul

Oh, tudo bem então.
Freira vazando

52 bytes se você usar um lambda! ()->(""+java.nio.ByteOrder.nativeOrder()).charAt(0);
Shaun Wild

6

Perl, 38 36 bytes

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

Funciona colocando um número na ordem de bytes padrão do sistema e comparando-o com um número compactado na ordem de bytes little-endian.


6

(G) Em diante, 24 bytes

here $4200004C , c@ emit

Supõe que as células tenham 32 bits (e que o seu quarto intérprete suporta os prefixos base de Gforth ). Ele simplesmente armazena o número 0x4200004C na memória e, em seguida, exibe o byte na extremidade inferior.


5

C, 34 bytes

Isso pressupõe a codificação de caracteres ASCII

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

Ligue sem argumento.

Explicação:

Na chamada, aserá 1. *(char*)aacessa o primeiro byte de a, que nas plataformas little-endian será 1, nas plataformas big-endian será 0.

Em plataformas big endian, esse código passará 66 + 10 * 0 = 66 para putchar. 66 é o código ASCII para B. Em plataformas little-endian, ele passará 66 + 10 * 1 = 76, que é o código ASCII para L.


5

C #, 60 52 bytes

C # é surpreendentemente competitivo neste.

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

Créditos ao Groo para a sintaxe C # 6.

60 bytes:

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

Com a sintaxe C # 6, você pode reduzi-lo um pouco: é char e=>System.BitConverter.IsLittleEndian?'L':'B';claro que isso (assim como a resposta Java) não imprime o valor.
Groo

Bem-vindo à programação de quebra-cabeças e código de golfe! Esta é uma boa primeira resposta.
28416 Alex A.

5

Julia, 24 19 bytes

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

Esta é uma função anônima que não recebe entrada e retorna a Char. Para chamá-lo, atribua-o a uma variável. Ele assume que os números inteiros são de 64 bits.

A ntohfunção converte a endianidade do valor passado a ele da ordem de bytes da rede (big endian) para a usada pelo computador host. Nas máquinas big endian, ntohé a função de identidade, pois não há conversão a ser feita. Em pequenas máquinas endian, os bytes são trocados, portanto ntoh(5) == 360287970189639680. O que também é, talvez mais legível, igual a: 0000010100000000000000000000000000000000000000000000000000000000em binário.

Se mudarmos o resultado de ntoh(5)55, obteremos 0 em máquinas endian grandes e 10 em máquinas endian pequenas. Adicionando isso à constante de caractere 'B', obteremos 'B'ou 'L'para grandes ou pequenas máquinas endian, respectivamente.

Economizou 5 bytes graças a FryAmTheEggman e Dennis!


Para 32 bits, você teria que mudar de 55 para 23 (também o 5 no 16 bits deveria ter sido 7, meu erro). Eu acho que Dennis quis dizer algo como ()->ntoh(5)>>55+'B':?
FryAmTheEggman

11
f()='L'-ntoh(10)%16e f()='L'-ntoh(10)&10deve funcionar em todas as plataformas.
Dennis


5

Lisp comum, 27 bytes

Testado em SBCL e ECL. Para uma abordagem portátil, deve-se usar recursos triviais .

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

A #+notação é uma condição de tempo de leitura , que o próximo formulário apenas se a expressão condicional for avaliada como verdadeira. Aqui, a condição é o #+big-endiantexto completo , o que significa que o teste será satisfeito se a :big-endianpalavra - chave pertencer à *FEATURES*lista (uma lista que contém, entre outras coisas, informações específicas da plataforma). A seguinte expressão é 'B, que é lida ou ignorada de acordo com o resultado do teste. Se sua plataforma é big-endian e você escreve o formulário acima no REPL, é exatamente como se você tivesse escrito o seguinte:

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

(NB. CL-USER>É o prompt)

O corpo de uma função é implícito PROGN, significando que somente a avaliação da última expressão é retornada. Assim, o acima realmente retorna símbolo B. Se, no entanto, a condição de tempo de leitura for avaliada como falsa, o formulário será lido como se você tivesse escrito:

CL-USER>(lambda()'L)

... que simplesmente retorna o símbolo L.


Snippets não são permitidos; escreva programas ou funções completos.
Erik the Outgolfer

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Atualizado, obrigado
coredump

Nota: Snippets são permitidos apenas se explicitamente permitido pelo OP.
Erik the Outgolfer

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Você poderia fornecer uma referência para isso? Existem outras respostas REPL aqui e / ou snippets de shell, e essa meta post sugere que as respostas REPL podem estar ok por padrão. Obrigado.
Coredump

5

ARMv6 e posterior: código de máquina de 20 bytes

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)

Não testado, pois não tenho uma máquina adequada à mão. O bit 9 do CPSR fornece a capacidade de carga / armazenamento atual.


Você pode usar um retorno da função ( BX lr, é?) Em vez de putchar, porque r0é o registro adequado para o resultado retornado.
anatolyg

De fato, isso (na verdade MOV pc, lr) estava em uma das minhas edições anteriores. No entanto, isso atende à especificação para imprimir a carta, não apenas devolvê-la.
user1908704

Talvez eu esteja lendo a referência incorretamente, mas acho que isso pode ser feito na codificação da instrução "thumb 2". Isso significaria que a primeira instrução permaneceu 32 bits ("codificando T1" na página F7-2720 do manual de referência do ARM v8, o que tornaria 0xF3EF_8000); o segundo também possui 32 bits (a codificação do operando é um pouco bizarra, mas pode ser feita com "i: imm3" definido como 0010 e "imm8" como 00000010, que fornece uma instrução geral de 0xF010_2F02). Antes da terceira instrução, precisamos inserir "ITE EQ" (0xBF0C) para controlar as condições nas próximas duas instruções MOV, que se tornam 0x204C e ...
Jules

... 0x2042 (economizando 2 bytes no total). Então, a instrução BL final é um pouco difícil de representar, porque os bits do endereço que não conhecemos acabam espalhados entre os bits da instrução que conhecemos, mas também é uma codificação de 32 bits, portanto o resultado seria total de 18 bytes (F3 EF 80 00 F0 10 2F 02 BF 0C 20 4C 20 42 F? ?? ?? ??). Eu acredito que isso altera a arquitetura para o ARMv8 e posterior, embora possa funcionar no ARMv7 (?).
Jules

4

Perl 5, 21 + 1 = 22 bytes

Corra com perl -E.

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

Testado em amd64 (little-endian) e mips (big-endian).


A -Esinalização é realmente necessária na contagem de bytes? Você pode apenas dizer que usa o Perl 5.10 (já que o saycomando está disponível nesta versão)
Paul Picard

11
@PaulPicard Mas use 5.10.0;tem muitos mais bytes!
Anders Kaseorg

11
@PaulPicard Seu ponto de vista está errado. O Perl 5.10 requer a -Eopção ou a useinstrução for say.
Anders Kaseorg

3
-Eé "grátis" no PPCG. Não há necessidade de adicionar nada.
Ven

11
(no entanto, -ne -pnão são)
Ven

4

R, 28 23 bytes

substr(.Platform$endian,1,1)

.Platform$endianretorna bigse executado em big endian e littlese em pouco. Aqui, usando substr, ele retorna a primeira letra da saída, bou seja, ou l.

Como endiané o único objeto que começa com um eobjeto contido .Platform, podemos reduzi-lo graças à correspondência parcial com o seguinte código de 23 bytes:

substr(.Platform$e,1,1)

3

Clojure, 46 44 bytes

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

Esta é uma função que usa o Java embutido para obter o endianness da máquina. Em seguida, obtenha a representação da string que será ou "LITTLE_ENDIAN"ou "BIG_ENDIAN"e pegue o primeiro caractere de qualquer string escolhida e retorne-a.

Economizou 2 bytes graças a @ cliffroot .


O que é realmente clojure, é lisp ou java?
Freira vazando

@LeakyNun Talvez um LISP prático que funcione com Java? É difícil dizer.
milhas

#(nth(str(java.nio.ByteOrder/nativeOrder))0)é 2 bytes mais curto
cliffroot 28/07

3

Rubi, 3130 caracteres.

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

Hmm, deve ser uma maneira melhor. Conte 5 caracteres a menos se o caractere não precisar ser produzido, pois acho que outras soluções omitem a impressão. ou seja, remova a parte "puts" se você não quiser nada impresso.


Se bem me lembro, depois de Ruby 1.9, você pode usar ?Le ?Bno lugar de puts :Leputs "B"
Sherlock9

Eu acho que puts [76,66].pack("s")[0]vai funcionar.
Wayne Conrad

@ Sherlock9, obrigado, um char a menos. @WayneConrad, Talvez adicione sua resposta, não tenho uma grande máquina endian à mão para testar, mas no little endian funciona. Mas a mudança como esta não funciona: puts [76,66].pack("s>")[0]. Isso significa que é possível não estar trabalhando em big endian por algum motivo que eu não entendo bem. Mas este parece funcionar (derivado da sua solução) puts [19522].pack("s>")[0]. WDYT? Gostaria de saber se posso encontrar algum lugar para avaliar em big endian.
akostadinov 29/07

Infelizmente, também não tenho uma máquina big-endian para testar.
Wayne Conrad

3

Bash (e outros shells unix), 32 (33) bytes

Primeira e segunda tentativa:

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

Graças a Dennis, versão mais curta:

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

O echoutilitário gera uma nova linha, com valor hexadecimal 0A, e nenhuma outra saída. Pois <<<aé 61 0A.

O odutilitário, por padrão, interpreta a entrada como palavras de dois bytes, preenchida com zero se o número de bytes for ímpar e convertida em octal. Isso resulta na saída do eco interpretado como 0A 00, que é convertido em 005000big-endian ou 000012little-endian. 61 0Atorna 005141- se em little-endian e 060412em big-endian. O resultado completo do od também inclui dados de endereço e tamanho o que significa que não pode usar 0, 1ou 2para o teste.

O comando está bem definido para expor a persistência do sistema. Do padrão :

A ordem dos bytes usada na interpretação dos valores numéricos é definida pela implementação, mas deve corresponder à ordem na qual uma constante do tipo correspondente é armazenada na memória do sistema.

Notas de compatibilidade

Não tenho certeza se colocar echo|odaspas sem aspas duplas em volta deles [o que resulta em um argumento de três palavras para case] é suportado em todos os sistemas. Não tenho certeza se todos os sistemas suportam scripts de shell sem nova linha final. Tenho quase certeza, mas não 100%, do comportamento de od ao adicionar o byte de preenchimento em sistemas big-endian. Se necessário, echo apode ser usado para as versões portáteis. Todos os scripts funcionam em bash, ksh e zsh, e os portáteis funcionam em hífen.


Nenhuma das mudanças é necessária; basta colocar um shell em que ele funcione no fone de ouvido e pronto.
Dennis

11
@ Dennis Eu gosto de fazer esse tipo de análise ... mas é mais divertido se eu não encontrar algo fora do padrão que obtém uma resposta mais curta em bash ou zsh que os outros. Talvez eu vou ver o que pode ser feito com[[
Random832

11
Nada de errado com a análise. O último parágrafo parecia que você não tinha certeza se uma resposta específica do shell é válida ... od<<<a|grep -q 5&&echo L||echo Bdeve funcionar no Bash e em outros.
Dennis

Eu testei em uma VM big-endian e echo|odimprimi 0000000\n005000\n0000001como você esperava.
Dennis

@ user17752 Porque endianness não afeta a saída de od -a.
Random832

3

PHP, 16 bytes

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

Isso usa dois truques não usados ​​nas duas respostas existentes do PHP:

  1. O valor passado para pack () ou desempacotar () pode ser qualquer coisa, não apenas 0 ou 1.
  2. O operador XOR bit a bit ( ^) funciona em cadeias de caracteres e o resultado é apenas o da cadeia mais curta, evitando a necessidade de um operador ternário ou de indexação de cadeias.

2

Nó, 42 bytes

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

Pro: existe um builtin. Con: nomes de propriedades são muito longos


2

PowerShell, 44 bytes

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

O caractere 66 é Be 10 caracteres depois é o número 76 L,. Um valor booleano de "true" se torna 1quando convertido em um número. BitConverteré uma classe .NET padrão.


1

Raquete, 35 28 bytes

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

'Bou 'Lrespectivamente. Deixe-me saber se isso não é específico o suficiente :)



1

Haskell (usando tipos numéricos com tamanho restrito somente ao GHC), 75 bytes

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

(não testado em uma arquitetura big-endian, mas parece que deveria funcionar!)


1

K, 15 bytes

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

Explicação;

    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

Bash, 27 bytes

iconv -tucs2<<<䉌|head -c1

( L + 424C ) é codificado como três bytes UTF-8: E4 89 8C.

Supõe-se que iconvuse a função glibc e que um código de idioma UTF-8 seja usado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.