Поміняйте своєю ендіанством


20

Як більшість із вас, напевно, знаєте, апаратні пам'яті (на байт) можна розділити на дві категорії - маленькі та великі . У мало-ендіанських спогадах байти нумеруються, починаючи з 0 на малому (найменш значущому) кінці, а у великих-ендіанських - навпаки.

Веселий факт : Ці умови засновані на книзі Джонатана Свіфта « Подорожі Гуллівера», де король Ліліпут наказав своїм громадянам розбивати яйця на кінці (таким чином, маленькі ендіанці), і повстанці розбили їх на великому кінці.

Як працює заміна

Припустимо, у нас є непідписане ціле число (32 біт) 12648430в пам'яті машини з великим ендіаном, яке може виглядати так:

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

Інвертуючи порядок байтів, ми отримуємо шістнадцяткове число, 0xEEFFC000яке знаходиться 4009738240в десятковій частині.

Ваше завдання

Напишіть програму / функцію, яка отримує непідписане 32-бітове ціле число у десятковій частині та виводить отримане ціле число під час заміни ендіанності, як описано вище.

Правила

  • Введення завжди буде в діапазоні 0до4294967295
  • Вихідні дані можуть бути надруковані в режим STDOUT (остаточні рядки / пробіли є прекрасними) або повернуті
  • Введення та вихід є десятковими
  • Поведінка неправильного введення не визначається

Тестові кейси

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

Чи відповідає "відповідь функції" чи "введення та виведення знаків у десятковій формі" означає чи рядок знаків з цифрами або масив знаків цифр? Чи може відповідь функції використати природне ціле подання цілочисельних значень своєї мови, яке в більшості випадків не має нічого спільного з "десятковим"?
aschepler

1
@aschepler Ціле значення мови, наприклад. 42задається у десятковій формі, але технічно це, наприклад, у двійковій символі С. Ви, звичайно 0x2a, можете вводити те, що я хотів запобігти - це введення даних як рядка "2a"або подібного.
ბიმო

Пов’язано (оскільки цей виклик просто переконайтеся, що спочатку слід перейти на 32 біти)
FlipTack

Відповіді:


25

x86_32 машинна мова, 3 байти

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

Це трохи обман. Конвенція виклику регістру Паскаля (див. Вікіпедія ) схожа на __fastcall, за винятком того, що він передає перший параметр в eax, а eax також містить повернене значення. Це також очищення callee, але оскільки ми не використовуємо стек ні для чого іншого, крім вказівника повернення, нам нічого не потрібно робити. Це дозволяє нам уникати mov або xchg і просто використовувати bswap безпосередньо.


Зауважте, що bswapпотрібен 80486 або вище :)
Світловий кот

@ceilingcat Дуже вірно, хоча я впевнений, що це неявно стосується багатьох інших рішень тут через обмеження компілятора чи інструментарію!
Поліном

10

x86_64 машинна мова Linux, 5 4 байти

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

Завдяки @peter ferrie за -1.

Спробуйте в Інтернеті!


це не десяткове повернене значення. Я не думаю, що це має значення. Крім того, ви можете xchg edi, eax на 4 байти.
peter ferrie

@peterferrie Нічого, я просто переглядав ваш веб-сайт, читаючи про заголовки PE!
Світловий кот


6

Japt , 10 14 байт

sG ùT8 ò w ¬nG

Спробуй це


Пояснення

Перетворіть ціле число вхідного рядка в базовий-16 ( sG), використовуйте 0для прокладки початку до довжини 8 ( ùT8), розділіть на масив з 2-х символьних рядків ( ò), зворотний ( w), приєднайтеся до рядка ( ¬) і перетворіть назад в базовий- 10 ( nG).


Ви знаєте, що може бути корисною функцією - мати більше таких функцій y, коли функція отримує функцію, застосуйте їх нормальне перетворення, запустіть функцію, а потім переверніть перетворення. У цьому випадку я думаю, що це дозволить скоротити його sG_ò w ¬до 8 байт. Або якби òце теж було, це може бути навіть sG_ò2_wза 7 ...
ETHproductions

@ETHproductions Я підтримую це; недо- &.Прислівник в J робить це , і це іноді дуже корисно в гольф. Хоча кодування у всіх інверсіях може бути втомливим.
cole

@ETHproductions: чим більше "перевантаження", тим краще :) Я написав це, витягуючи пінти і спочатку мав sG_òw..., не міг за все життя зрозуміти, чому це не вийде! Зрештою, я зрозумів свою помилку!
Кудлатий

Здається, не працює для введення менше 2 << 24 ...
Ніл

Спасибі, @Neil; буде виправлено це згодом. Схоже, це обійдеться мені в 4 байти.
Кудлатий



5

APL + WIN 14 байт

256⊥⌽(4⍴256)⊤⎕

Пояснення

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

1
Буде 256⊥⌽⎕⊤⍨4⍴256працювати на -1 байт?
Erik the Outgolfer

Оператор ⍨ недоступний у APL + WIN, тому відповідь "ні", але це може бути так для "Dyalog APL"
Грем

5

C # , 70 68 байт

Мабуть, це не оптимально.

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

Спробуйте в Інтернеті!


Ви можете перемістити призначення у returnвираз, а потім використати синтаксис тіла, що має вираз: uint e(uint n)=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;на 64 байти.
hvd

@hvd Це не відображається як для мене синтаксис, що відповідає дійсності. Однак мені вдалося використати трюк перестановки зсуву, щоб голити 2 байти.
Поліном

Я скопіював і вставив з мого коментаря у ваше посилання TIO, щоб переконатися, що не було помилок друку чи чогось подібного, і саме так, як у моєму коментарі, це працює: TIO посилання
hvd

Я помітив, що 0xFF00FF00 є доповненням до 0xFF00FF і цікаво, чи можете ви цим скористатися? Але оголосивши її змінною, потрібно занадто багато символів
PrincePolka

Ой! Добре перевірити константи дійсно: ви можете використовувати 0xFF00FFдва рази, використовуючи >>ing перед &ing, а потім можете скоротити їх 0xFF00FFдо ~0u/257: uint e(uint n)=>((n=n>>16|n<<16)>>8&~0u/257)|(n&~0u/257)<<8;для 60. TIO посилання
hvd


4

05AB1E , 12 10 байт

3F₁‰R`})₁β

Спробуйте в Інтернеті! Пояснення:

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

1
Це, здається, не є правильним рішенням. "Прокладка", яку ви робите, насправді повторює список байтів на довжину 4.
Ерік Вигнавець

@EriktheOutgolfer Ба, я хотів би, щоб документація насправді сказала, що ...
Ніл,

3

JavaScript (ES6), 45 43 байт

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

1
Починаючи з t=0економії 2 байтів:f=(n,p=t=0)=>t++<4?f(n>>>8,p*256+n%256):p
Арнольд


3

MATL , 12 10 байт

7Y%1Z%P7Z%

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

        % 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 байт

Збережено 6 байт за допомогою @ Ніла

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

Тестові кейси


Приємно, найкраще, що я міг отримати з рекурсією f=(n,p=0,t=4)=>t?f(n/256|0,p*256+n%256,t-1):p.
ETHproductions

@ETHproductions ... це коротше?
Erik the Outgolfer

1
@ETHproductions Це, безумовно, коротше. Ви повинні опублікувати його.
Арнольд

46 байт:n=>(n>>>24|n>>8&65280|n<<8&16711680|n<<24)>>>0
Ніл

1
@hvd Не хвилюйтесь. Ви можете додати його як альтернативну версію або повністю замінити існуючу. До вас!
Арнольд

2

J, 16 байт

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

Спробуйте в Інтернеті!

Робота над скороченням правого виразу. Я думаю, що я можу поголити кілька байтів, зробивши цю роботу з бета-версією J. Я клянусь, що тут побачив, що ви можете закінчити поїзд із іменником у новій бета-версії ...

Пояснення

|.&.((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

Перетворити на чотири цифри бази 256, перевернути цифри, а потім перетворити назад у десяткові. В основному виконуйте алгоритм, який передбачений в ОП. Це, мабуть, один раз, коли корисно, що змішане базове перетворення J вимагає вказати кількість цифр, хоча було б у 2 рази менше байтів, якби я міг закінчити поїзд на іменнику ( (#:~4#256)замість нього).


2

Excel VBA, 103 92 байт

Анонімна функція негайного вікна VBE, яка приймає вхід із діапазону, [A1]перетворюється на шістнадцятковий, обертає байти та виводить у безпосереднє вікно 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)]

Чи можу я це десь перевірити? Чи можете ви додати онлайн-перекладача?
ბიმო

2
@BruceForte Ні, на жаль, немає жодних онлайн-перекладачів для жодного з варіантів VBA, однак, якщо у вас є копія Excel на комп'ютері, ви можете отримати доступ до VBE, натиснувши Alt + F11, а потім безпосереднє вікно, натиснувши Ctrl + G. Для цієї анонімної функції ви потім вставите свій внесок у комірку А1 та код вище у безпосереднє вікно та натисніть клавішу Enter
Тейлор Скотт

О, а іноді VBA є трохи прикольним (а версія для Mac - це значно гірше, ніж версія Windows), тому це, і якщо все не вказано інше, рішення VBA передбачають 32-бітну версію Windows
Тейлор Скотт

2

Збірка КПП (32-розрядна), 8 байт

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

Як це працює:

  • Конвенція виклику КПП ставить перший 32-розрядний параметр слова в SP + 24 та тіні, які адресуються в GPR3.
  • LWBRX приймає навантаження GPR3 ​​(третій операнд) і нульово розширює його (другий операнд) в EA, потім зчитує 4 байти в зворотному порядку і зберігає його в GPR3 ​​(перший операнд).
  • GPR3 утримує повернене значення.
  • BLR повертається з функції (гілки на адресу в регістрі LR)

На жаль, немає жодних онлайн-емуляторів складання КПП, які я міг би продемонструвати. Вибачте!


2

Befunge, 62 61 або 49 байт

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

Спробуйте в Інтернеті!

Для цього використовується стандартний Befunge в довідковому інтерпретаторі, і тому нам потрібно враховувати той факт, що осередки пам'яті є 8-бітними підписами та правильні для можливого переповнення підпису.

На реалізаціях з непідписаними комірками пам’яті (наприклад, PyFunge) або там, де діапазон перевищує 8 біт (наприклад, FBBI), ми можемо вийти без цих перевірок, заощадивши 12 байт.

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

Спробуйте FBBI онлайн!
Спробуйте PyFunge онлайн!

Хоча зауважте, що PyFunge має помилку обробки цілочисленних помилок, тому при тестуванні на TIO вам потрібно слідкувати за номером у полі введення з пробілом або переривом рядка.


2

Октава , 10 байт

@swapbytes

Спробуйте в Інтернеті!

Це може бути перший раз, коли Octave має такий самий результат, як і його похідне для гольфу, MATL. Звичайно, у цьому випадку Octave має вбудований, а не MATL, що робить його набагато простіше.

Визначає ручку до вбудованої swapbytes, яка приймає будь-який тип даних, замінює ендіанси та видає результат. У цьому випадку вхід є 32-бітним цілим числом без знаку.



2

R , 86 байт

Я подумав, що у R вже було відповідь (або дві) на це запитання, але, мабуть, я помилився, або у них були ті самі проблеми, що й у мене з R, не роблячи підписані вступи. Це питання витягнуло будь-які побудови, які могли допомогти. Я спробував конверсію 256 базових, але це виявилося довгим, але я думаю, що для цього є хтось розумніший, ніж я, щоб зробити це. Тоді я закінчив наступне, що це перетворення на базі 2, змінюючи порядок на рекурсивну функцію.

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)

Спробуйте в Інтернеті!

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

Ви мали рацію про те, що база 256 була коротшою!
Джузеппе

@Giuseppe, ти збираєшся одягнути шапку, чи не ти
MickyT

2

R , 41 байт

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

Спробуйте в Інтернеті!

Перевірте всі тестові випадки!

Використовує конверсію базової 256, як запропонував MickyT тут . R не має підписаних 32-бітових цілих чисел, а також не має 64-бітних цілих чисел. Це заважає нам використовувати побітові операції, але цей підхід (і, швидше за все, MickyT), ймовірно, ще коротший, оскільки побітові оператори R є досить багатослівними.

Використовує номер 4 цієї підказки , враховуючи, що ми ніколи не отримуємо величину 256^4.

n%/%256^(0:3)%%256витягує байти і %*%, матричний добуток, є точковим продуктом у цій ситуації, 256^(3:0)здійснюючи зворотний порядок байт. %*%поверне 1x1, matrixщо містить значення, повернене до кінця.


1

CP-1610 збірка, 6 DECLE = 8 байт

Цей код призначений для запуску на Intellivision .

Опкод CP-1610 кодується з 10-бітовим значенням, відомим як "DECLE". Ця функція становить 6 DECLE, починаючи з $ 480C і закінчуючи $ 4811.

CP-1610 має 16-бітні регістри, тому ми використовуємо два з них (R0 і R1) для зберігання 32-бітного значення.

                               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

Дамп виконання

 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

Чому це 7,5 байт? Я думаю, це має бути 8 байт.
Ерік Атголфер

@EriktheOutgolfer Ярмарок досить. Оновлено відповідно.
Арнольд

@EriktheOutgolfer Тому що 60 біт дорівнює 7,5 байт?
Jeppe Stig Nielsen

@JeppeStigNielsen Це правда, але файл ніколи не може бути довжиною 7,5 байт, він буде до- або після додавання до 0.
Ерік Атголфер

@EriktheOutgolfer Технічно це дійсно може бути збережено всередині 10-бітного ПЗУ. Ось приклад аркуша специфікації. (Сьогодні ми використовуємо 16-бітний ПЗУ для домашніх ігор Intellivision, але ще в той час мікросхеми пам'яті були настільки дорогими, що використання 10-бітних було справжнім заощадженням грошей.)
Арнольд,

1

C # (.NET Core) , 72 + 31 = 103 байти

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

Спробуйте в Інтернеті!

+31 для using System;using System.Linq;

Я сподівався використати Array.Reverse вбудований, але цього не повинно бути (див. Альтернативу нижче).

C # (.NET Core) , 87 + 13 = 100 байт

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

Спробуйте в Інтернеті!

+13 для using System;

Це рішення піклується про @JeppeStigNielsen; знявши обмеження наявності всього вбудованого збереженого 3-х байт.


Оскільки ви можете заощадити using System.Linq;, це все ще може бути дешевшим у використанні x=>{var a=BitConverter.GetBytes(x);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}.
Джеппе Стіг Нільсен

1

REXX , 42 байти

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

Спробуйте в Інтернеті!

Безголівки:

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

Мова машин ARM Linux, 8 байт

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

Щоб спробувати це самостійно, компілюйте та запустіть наступне на пристрої Raspberry Pi або Android, на якому працює 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

К4 , 18 байт

Рішення:

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

Приклади:

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

Пояснення:

Немає неподписаних вводів, тому введення приймається як довге.

Перетворити в логічний масив (64 біт), змінити форму, змінити назад, взяти перші 8 байт, перетворити назад у довгі.

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

Бонус:

19-байтна версія в ОК, яку можна спробувати в Інтернеті!

2/,/8#|12 8#(64#2)\
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.