Échangez l'endianité


20

Comme la plupart d'entre vous le savent probablement, les mémoires matérielles (adressables en octets) peuvent être divisées en deux catégories - petit-boutien et gros-boutiste . Dans les mémoires little-endian, les octets sont numérotés en commençant par 0 à la petite extrémité (la moins significative) et dans les mémoires big-endian dans l'autre sens.

Fait amusant : ces termes sont basés sur le livre de Jonathan Swift , Gulliver's Travels, dans lequel le roi lilliputien a ordonné à ses citoyens de casser leurs œufs sur le petit bout (donc les petits-bouts) et les rebelles cassaient le leur sur le grand bout.

Comment fonctionne l'échange

Supposons que nous ayons un entier non signé (32 bits) 12648430en mémoire, dans une machine big-endian qui pourrait ressembler à ceci:

  addr: 0  1  2  3
memory: 00 C0 FF EE

En inversant l'ordre des octets, nous obtenons l'entier hexadécimal 0xEEFFC000qui est 4009738240en décimal.

Ta tâche

Écrivez un programme / fonction qui reçoit un entier 32 bits non signé en décimal et sort l'entier résultant lors de l'échange de l'endianité comme décrit ci-dessus.

Règles

  • L'entrée sera toujours dans la plage 0de4294967295
  • La sortie peut être imprimée sur STDOUT (les sauts de ligne / espaces sont très bien) ou retournés
  • L'entrée et la sortie sont en décimal
  • Le comportement sur une entrée non valide n'est pas défini

Cas de test

0 -> 0
1 -> 16777216
42 -> 704643072
128 -> 2147483648
12648430 -> 4009738240
16885952 -> 3232235777
704643072 -> 42
3735928559 -> 4022250974
4009738240 -> 12648430
4026531839 -> 4294967279
4294967295 -> 4294967295

Pour une réponse de fonction, «l'entrée et la sortie sont-elles en décimales» signifie-t-il qu'une chaîne de caractères numériques ou un tableau de valeurs numériques est requis? Ou une réponse de fonction peut-elle utiliser la représentation de la valeur entière naturelle de son langage, qui dans la plupart des cas n'a absolument rien à voir avec "décimal"?
aschepler

1
@aschepler La valeur entière du langage, par exemple. 42est donné en décimal mais techniquement c'est en binaire en C par exemple. Vous pouvez bien sûr taper 0x2a, ce que je voulais éviter, c'est de prendre l'entrée comme une chaîne similaire "2a"ou similaire.
ბიმო

Connexes (car ce défi consiste à s'assurer d'abord de
passer

Réponses:


25

langage machine x86_32, 3 octets

endian_swap:        # to be called with PASCAL REGISTER calling convention
0f c8    bswap eax
c3       ret

C'est un peu une triche. La convention d'appel Pascal registre (voir Wikipedia ) est un peu comme __fastcall, sauf qu'elle passe le premier paramètre dans eax, et eax contient également la valeur de retour. Il s'agit également d'un nettoyage de l'appel, mais comme nous n'utilisons la pile pour rien d'autre que le pointeur de retour, nous n'avons rien à faire. Cela nous permet d'éviter un mov ou un xchg et d'utiliser directement bswap.


Vous voudrez peut-être noter que bswapnécessite un 80486 ou supérieur :)
plafondcat

@ceilingcat Très vrai, même si je suis sûr que c'est implicitement le cas pour de nombreuses autres solutions ici en raison de restrictions du compilateur ou de la chaîne d'outils!
Polynôme

10

x86_64 langage machine Linux, 5 4 octets

0:       0f cf                   bswap  %edi
2:       97                      xchg   %eax,%edi
3:       c3                      retq 

Merci à @peter ferrie pour -1.

Essayez-le en ligne!


ce n'est pas une valeur de retour décimale. Je ne pense pas que cela compte. En outre, vous pouvez xchg edi, eax pour 4 octets.
peter ferrie

@peterferrie Wow Je parcourais juste votre site Web en lisant les en-têtes PE!
Plafond du


6

Japt , 10 14 octets

sG ùT8 ò w ¬nG

Essayez-le


Explication

Convertir un entier d'entrée en une chaîne de base-16 ( sG), utiliser 0pour remplir le début à la longueur 8 ( ùT8), diviser en un tableau de 2 chaînes de caractères ( ò), inverser ( w), rejoindre à une chaîne ( ¬) et reconvertir en base- 10 ( nG).


Vous savez, ce qui pourrait être une fonctionnalité pratique, c'est d'avoir plus de fonctions comme ycelle-ci, lorsqu'une fonction est affectée à une fonction, appliquer sa transformation normale, exécuter la fonction, puis inverser la transformation. Dans ce cas, je pense que cela permettrait de le raccourcir à sG_ò w ¬8 octets. Ou si òc'était le cas aussi, ça pourrait même être sG_ò2_wpour 7 ...
ETHproductions

@ETHproductions Je le soutiens; le sous- &.adverbe de J le fait et il est parfois très utile pour jouer au golf. Le codage dans toutes les inversions pourrait cependant être fastidieux.
cole

@ETHproductions: plus il y a de "surcharge", mieux c'est :) J'ai écrit ceci en tirant des pintes et à l'origine sG_òw..., je ne pouvais pas, pour la vie de moi, comprendre pourquoi cela ne fonctionnerait pas! J'ai finalement réalisé mes erreurs!
Shaggy

Ne semble pas fonctionner pour une entrée inférieure à 2 << 24 ...
Neil

Merci, @Neil; obtiendra ce problème plus tard. On dirait que ça va me coûter 4 octets.
Shaggy



5

APL + WIN 14 octets

256⊥⌽(4⍴256)⊤⎕

Explication

⎕ prompt for screen input
(4⍴256)⊤ 4 byte representation in base 256
⌽ reverse bytes
256⊥ bytes from base 256 to integer

1
Fonctionnerait 256⊥⌽⎕⊤⍨4⍴256pour -1 octet?
Erik the Outgolfer

L'opérateur ⍨ n'est pas disponible en APL + WIN donc la réponse est non mais cela pourrait bien être oui pour Dyalog APL
Graham

5

C # , 70 68 octets

Ce n'est probablement pas optimal.

68:

Func<uint,uint>f=n=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;

70:

uint e(uint n){n=n>>16|n<<16;return(n&0xFF00FF00)>>8|(n&0xFF00FF)<<8;}

Essayez-le en ligne!


Vous pouvez déplacer l'affectation dans l' returnexpression, puis utiliser la syntaxe des membres avec corps d'expression: uint e(uint n)=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;pour 64 octets.
hvd

@hvd Cela ne s'affiche pas comme une syntaxe valide basée sur l'expression pour moi. J'ai cependant pu utiliser l'astuce de réarrangement de décalage pour raser 2 octets.
Polynôme

J'ai copié et collé de mon commentaire dans votre lien TIO pour m'assurer qu'il n'y avait pas de fautes de frappe ou quelque chose comme ça et exactement comme c'est dans mon commentaire, cela fonctionne: Lien TIO
hvd

J'ai remarqué que 0xFF00FF00 est le complément de 0xFF00FF et je me demande si vous pouvez en profiter? Mais la déclarer une variable prend trop de caractères
PrincePolka

Oh! Bon pour vérifier les constantes en effet: vous pouvez utiliser 0xFF00FFdeux fois en >>ing avant &ing, puis vous pouvez raccourcir 0xFF00FFà ~0u/257: uint e(uint n)=>((n=n>>16|n<<16)>>8&~0u/257)|(n&~0u/257)<<8;pour 60. Lien TIO
hvd


4

05AB1E , 12 10 octets

3F₁‰R`})₁β

Essayez-le en ligne! Explication:

  ₁         Integer constant 256
   ‰        [Div, Mod]
    R       Reverse
     `      Flatten to stack
3F    }     Repeat 3 times
       )    Collect results
        ₁β  Convert from base 256

1
Cela ne semble pas être une solution valable. Le "remplissage" que vous faites consiste en fait à répéter la liste des octets jusqu'à la longueur 4.
Erik the Outgolfer

@EriktheOutgolfer Bah, j'aurais aimé que la documentation dise que ...
Neil

3

JavaScript (ES6), 45 43 octets

f=(n,p=0,t=4)=>t?f(n>>>8,p*256+n%256,t-1):p

1
Commencer par t=0enregistre 2 octets:f=(n,p=t=0)=>t++<4?f(n>>>8,p*256+n%256):p
Arnauld


3

MATL , 12 10 octets

7Y%1Z%P7Z%

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

        % Implicitly input a number, read as a double
7Y%     % Cast to uint32
1Z%     % Convert to uint8 without changing underlying data. The result is 
        % an array of four uint8 numbers, each corresponding to a byte of
        % the original number's representation 
P       % Flip array
7Z%     % Convert back to uint32 without changing underlying data. The array
        % of four uint8 numbers is interpreted as one uint32 number.
        % Implicitly display

2

JavaScript (ES6), 51 45 octets

6 octets enregistrés avec l'aide de @ Neil

n=>(n>>>24|n>>8&65280|(n&65280)<<8|n<<24)>>>0

Cas de test


Bien, le mieux que j'ai pu obtenir avec la récursivité était f=(n,p=0,t=4)=>t?f(n/256|0,p*256+n%256,t-1):p.
ETHproductions

@ETHproductions ... c'est plus court?
Erik the Outgolfer

1
@ETHproductions C'est nettement plus court. Vous devez le poster.
Arnauld du

46 octets:n=>(n>>>24|n>>8&65280|n<<8&16711680|n<<24)>>>0
Neil

1
@hvd Pas de soucis. Vous pouvez soit l'ajouter en tant que version alternative, soit remplacer entièrement la version existante. Dépend de vous!
Arnauld

2

J, 16 octets

|.&.((4#256)#:])

Essayez-le en ligne!

Travailler à raccourcir l'expression de droite. Je pense que je peux raser quelques octets en faisant cela avec une version beta J. Je jure que j'ai vu ici que vous pouvez terminer un train avec un nom dans une nouvelle version bêta ...

Explication

|.&.((4#256)#:])
    ((4#256)#:])  Convert to 4 two-byte blocks
            #:      Debase to
      4#256         4 digits base 256
  &.              Apply right function, left function, then inverse of right
|.                Reverse digits

Convertissez en 4 chiffres base 256, inversez les chiffres, puis reconvertissez en décimal. Fondamentalement, exécutez l'algorithme fourni dans l'OP. C'est peut-être la seule fois où il est utile que la conversion de base mixte de J vous oblige à spécifier le nombre de chiffres, bien que ce serait 2 octets de moins si je pouvais terminer le train dans un nom (à la (#:~4#256)place).


2

Excel VBA, 103 92 octets

Fonction de fenêtre immédiate VBE anonyme qui prend les entrées de la plage [A1]convertit en hexadécimal, inverse les octets et sort dans la fenêtre immédiate VBE

h=[Right(Rept(0,8)&Dec2Hex(A1),8)]:For i=0To 3:s=s+Mid(h,7-2*i,2):Next:[B1]=s:?[Hex2Dec(B1)]

Puis-je tester cela quelque part? Pourriez-vous ajouter un interprète en ligne, s'il vous plaît?
ბიმო

2
@BruceForte Non, malheureusement il n'y a pas d'interprète en ligne pour aucune des variantes de VBA, cependant, si vous avez une copie d'Excel sur votre ordinateur, vous pouvez accéder au VBE en appuyant sur Alt + F11, puis sur la fenêtre immédiate en appuyant sur Ctrl + G. Pour cette fonction anonyme, vous devez ensuite coller votre entrée dans la cellule A1 et le code ci-dessus dans la fenêtre immédiate et appuyez sur Entrée
Taylor Scott

Oh - et parfois VBA est un peu génial (et la version Mac est pire que la version Windows) donc cela, et sauf indication contraire, les solutions VBA supposent la version Windows 32 bits par défaut
Taylor Scott

2

Assemblage PPC (32 bits), 8 octets

endian_swap:    # WORD endian_swap(WORD)
7c 60 1c 2c     LWBRX 3,0,3
4e 80 00 20     BLR

Comment cela fonctionne:

  • La convention d'appel PPC place le premier paramètre de mot 32 bits dans SP + 24 et les ombres qui s'adressent dans GPR3.
  • LWBRX prend la charge GPR3 ​​(troisième opérande) et l'étend à zéro (deuxième opérande) dans EA, puis lit 4 octets dans l'ordre inverse et le stocke dans GPR3 ​​(premier opérande).
  • GPR3 détient la valeur de retour.
  • BLR revient de la fonction (branche à l'adresse dans le registre LR)

Malheureusement, il n'y a pas d'émulateurs d'assemblage PPC en ligne que je puisse trouver pour démontrer. Pardon!


2

Befunge, 62 61 ou 49 octets

0&0v!p22:/3g22/*:*82\+%*:*82+<
@.$_:28*:*%00p\28*:**00g28*:*^

Essayez-le en ligne!

Il s'agit de Befunge standard sur l'interpréteur de référence, et nous devons donc tenir compte du fait que les cellules de mémoire sont signées sur 8 bits et corriger tout débordement signé possible.

Sur les implémentations avec des cellules de mémoire non signées (par exemple PyFunge), ou lorsque la plage est supérieure à 8 bits (par exemple FBBI), nous pouvons nous en passer sans ces vérifications, en économisant 12 octets.

0&0v!p22:/3g22/*:*82\+g<
@.$_:28*:*%00p\28*:**00^

Essayez FBBI en ligne!
Essayez PyFunge en ligne!

Bien que notez que PyFunge a une entrée entière de traitement des bogues, donc lors des tests sur TIO, vous devez suivre le nombre dans le champ de saisie avec un espace ou un saut de ligne.


2

Octave , 10 octets

@swapbytes

Essayez-le en ligne!

C'est peut-être la première fois qu'Octave obtient exactement le même score que son dérivé du golf, MATL. Bien sûr, dans ce cas, c'est Octave qui a le intégré, plutôt que MATL, ce qui le rend beaucoup plus facile.

Définit un handle vers le intégré swapbytes, qui prend n'importe quel type de données, échange l'endianité et génère le résultat. Dans ce cas, l'entrée est un entier non signé 32 bits.



2

R , 86 octets

Je pensais qu'il y avait déjà une réponse (ou deux) dans R pour cette question, mais je devais me tromper ou ils avaient les mêmes problèmes que moi avec R ne faisant pas de signature. Ce problème a supprimé tous les éléments intégrés qui auraient pu aider. J'ai essayé la conversion de base 256, mais cela a fini par être trop long, mais je pense qu'il y a encore de la place pour quelqu'un de plus intelligent que moi pour le faire. Ensuite, je me suis retrouvé avec ce qui suit, une conversion en base 2 échangeant l'ordre dans une fonction récursive.

f=function(x,y=0,i=31)'if'(i+1,f(x-(2^i*z),y+(2^((3-i%/%8)*8+i%%8)*(z=2^i<=x)),i-1),y)

Essayez-le en ligne!

f=function(x,y=0,i=31)       # set up the function and initial values
  'if'(i+1,                  # test for i >= 0
    f(                       # recursively call the function
      x-(2^i*z),             # remove 2^i from x when 2^i <= x
      y+(2^                  # add to y 2 to the power of
        ((3-i%/%8)*8+i%%8)   # calc to swap the order of the bytes
        *(z=2^i<=x)),        # when 2^i <= x
      i-1),                  # decrement i
   y)                        # return y

vous aviez raison sur la base 256 étant plus courte!
Giuseppe

@Giuseppe, vous allez mettre un chapeau, n'est-ce pas
MickyT

2

R , 41 octets

function(n)n%/%256^(0:3)%%256%*%256^(3:0)

Essayez-le en ligne!

Vérifiez tous les cas de test!

Utilise une conversion en base 256 comme MickyT l'a suggéré ici . R n'a pas d'entiers 32 bits non signés, pas plus qu'il n'a d'entiers 64 bits. Cela nous empêche d'utiliser des opérations au niveau du bit mais cette approche (et probablement celle de MickyT) est probablement encore plus courte car les opérateurs au niveau du bit de R sont assez verbeux.

Utilise le numéro 4 de cette astuce , en tenant compte du fait que nous n'obtenons jamais un nombre aussi grand que 256^4.

n%/%256^(0:3)%%256extrait les octets et %*%, le produit matriciel, est le produit scalaire dans cette situation, avec 256^(3:0)effet de l'ordre inversé des octets. %*%renverra un 1x1 matrixcontenant la valeur endian-inversée.


1

CP-1610Assemblage , 6 DECLEs = 8 octets

Ce code est destiné à être exécuté sur une Intellivision .

Un opcode CP-1610 est codé avec une valeur de 10 bits, connue sous le nom de «DECLE». Cette fonction est longue de 6 DECLEs, commençant à 480C $ et se terminant à 4811 $.

Le CP-1610 possède des registres 16 bits, nous utilisons donc deux d'entre eux (R0 et R1) pour stocker une valeur 32 bits.

                               ROMW  10           ; use 10-bit ROM

                               ORG   $4800        ; start program at address $4800

                               ;; example call
4800  0001                     SDBD               ; load 0xDEAD into R0
4801  02B8 00AD 00DE           MVII  #$DEAD, R0
4804  0001                     SDBD               ; load 0xBEEF into R1
4805  02B9 00EF 00BE           MVII  #$BEEF, R1

4808  0004 0148 000C           CALL  swap32       ; call our function

480B  0017                     DECR  PC           ; loop forever

                               ;; swap32 function
                       swap32  PROC

480C  0040                     SWAP  R0           ; 16-bit SWAP of R0
480D  0041                     SWAP  R1           ; 16-bit SWAP of R1

480E  01C1                     XORR  R0, R1       ; exchange R0 and R1
480F  01C8                     XORR  R1, R0       ; using 3 consecutive eXclusive OR
4810  01C1                     XORR  R0, R1

4811  00AF                     JR    R5           ; return

                               ENDP

Dump d'exécution

 R0   R1   R2   R3   R4   R5   R6   R7    CPU flags  instruction
 ------------------------------------------------------------------
 0000 4800 0000 0000 01FE 1041 02F1 4800  ------iq   SDBD
 0000 4800 0000 0000 01FE 1041 02F1 4801  -----D-q   MVII #$DEAD,R0
 DEAD 4800 0000 0000 01FE 1041 02F1 4804  ------iq   SDBD
 DEAD 4800 0000 0000 01FE 1041 02F1 4805  -----D-q   MVII #$BEEF,R1
[DEAD BEEF]0000 0000 01FE 1041 02F1 4808  ------iq   JSR  R5,$480C

 DEAD BEEF 0000 0000 01FE 480B 02F1 480C  ------iq   SWAP R0
 ADDE BEEF 0000 0000 01FE 480B 02F1 480D  S------q   SWAP R1
 ADDE EFBE 0000 0000 01FE 480B 02F1 480E  S------q   XORR R0,R1
 ADDE 4260 0000 0000 01FE 480B 02F1 480F  ------iq   XORR R1,R0
 EFBE 4260 0000 0000 01FE 480B 02F1 4810  S-----iq   XORR R0,R1
[EFBE ADDE]0000 0000 01FE 480B 02F1 4811  S-----iq   MOVR R5,R7

 EFBE ADDE 0000 0000 01FE 480B 02F1 480B  ------iq   DECR R7

Pourquoi est-ce 7,5 octets? Je pense que cela devrait être de 8 octets.
Erik the Outgolfer

@EriktheOutgolfer Assez juste. Mis à jour en conséquence.
Arnauld

@EriktheOutgolfer Parce que 60 bits équivalent à 7,5 octets?
Jeppe Stig Nielsen

@JeppeStigNielsen C'est vrai, mais un fichier ne peut jamais faire 7,5 octets de long, il sera pré ou post-complété avec 0s.
Erik the Outgolfer

@EriktheOutgolfer Techniquement, cela pourrait vraiment être stocké dans une ROM 10 bits. Voici un exemple de fiche technique. (Aujourd'hui, nous utilisons une ROM 16 bits pour les jeux homebrew d'Intellivision, mais à l'époque, les puces de mémoire étaient si chères que l'utilisation de 10 bits était une véritable économie d'argent.)
Arnauld

1

C # (.NET Core) , 72 + 31 = 103 octets

m=>BitConverter.ToUInt32(BitConverter.GetBytes(m).Reverse().ToArray(),0)

Essayez-le en ligne!

+31 pour using System;using System.Linq;

J'espérais utiliser Array.Reverse ligne, mais ce n'était pas le cas (voir alternative ci-dessous).

C # (.NET Core) , 87 + 13 = 100 octets

m=>{var a=BitConverter.GetBytes(m);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}

Essayez-le en ligne!

+13 pour using System;

Cette solution prend soin de @JeppeStigNielsen; supprimer la restriction d'avoir tout en ligne enregistré 3 octets.


Parce que vous pouvez économiser using System.Linq;, il peut être encore moins cher à utiliser x=>{var a=BitConverter.GetBytes(x);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}.
Jeppe Stig Nielsen

1

REXX , 42 octets

say c2d(left(reverse(d2c(arg(1))),4,'0'x))

Essayez-le en ligne!

Non golfé:

n=arg(1) -- take n as argument
n=d2c(n) -- convert from decimal to character (bytes)
n=reverse(n) -- reverse characters
n=left(n,4,'0'x) -- extend to four bytes, padding with zeros
n=c2d(n) -- convert from bytes to decimal again
say n -- output result


1

Langage machine ARM Linux, 8 octets

0:       e6bf0f30       rev     r0, r0
4:       e12fff1e       bx      lr

Pour essayer vous-même, compilez et exécutez ce qui suit sur un appareil Raspberry Pi ou Android exécutant GNUroot

#include<stdio.h>
#define f(x) ((unsigned int(*)(unsigned int))"0\xf\xbf\xe6\x1e\xff/\xe1")(x)
int main(){
  printf( "%u %u\n", 0, f(0) );
  printf( "%u %u\n", 1, f(1) );
  printf( "%u %u\n", 42, f(42) );
  printf( "%u %u\n", 128, f(128) );
  printf( "%u %u\n", 16885952, f(16885952) );
  printf( "%u %u\n", 704643072, f(704643072) );
  printf( "%u %u\n", 3735928559U, f(3735928559U) );
  printf( "%u %u\n", 4009738240U, f(4009738240U) );
  printf( "%u %u\n", 4026531839U, f(4026531839U) );
  printf( "%u %u\n", 4294967295U, f(4294967295U) );
}



1

K4 , 18 octets

Solution:

0b/:,/8#|12 8#0b\:

Exemples:

q)\
  0b/:,/8#|12 8#0b\:0
0
  0b/:,/8#|12 8#0b\:1
16777216
  0b/:,/8#|12 8#0b\:42
704643072
  0b/:,/8#|12 8#0b\:4294967295
4294967295
  0b/:,/8#|12 8#0b\:4026531839
4294967279

Explication:

Il n'y a pas d'entiers non signés, donc la saisie est longue.

Convertir en tableau booléen (64 bits), remodeler, inverser, prendre les 8 premiers octets, reconvertir en long.

0b/:,/8#|12 8#0b\: / the solution
              0b\: / convert to bits
         12 8#     / reshape into 12x8 grid (wraps)
        |          / reverse
      8#           / take first 8
    ,/             / flatten
0b/:               / convert to long

Prime:

Version 19 octets en oK que vous pouvez essayer en ligne!

2/,/8#|12 8#(64#2)\
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.