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


20

Как многие из вас, вероятно, знают, аппаратная память (с байтовой адресацией) может быть разделена на две категории - с прямым порядком байтов и с прямым порядком байтов . В воспоминаниях с прямым порядком байтов байты нумеруются, начиная с 0 на младшем (наименее значимом) конце, а в старших - наоборот.

Интересный факт : эти термины основаны на книге Джонатана Свифта « Путешествия Гулливера», в которой король-лилипутец приказал своим гражданам разбивать яйца на маленьком конце (таким образом, на маленьких концах), а повстанцы ломали свои яйца на большом конце.

Как работает обмен

Предположим, что у нас есть целое число без знака (32 бита) 12648430в памяти на машине с прямым порядком байтов, которая может выглядеть следующим образом:

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

Инвертируя порядок байтов, мы получаем шестнадцатеричное целое число, 0xEEFFC000которое находится 4009738240в десятичном виде.

Твое задание

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

правила

  • Input всегда будет находиться в диапазоне 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дается в десятичном виде, но технически это в двоичном в C, например. Вы можете, конечно, напечатать 0x2a, что я хотел предотвратить, так это принимать ввод в виде строки "2a"или тому подобного.
ბიმო

Связанный (так как эта задача - сначала
удостовериться в

Ответы:


25

машинный язык x86_32, 3 байта

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

Это немного обмануть. Соглашение о вызовах регистра Pascal (см. Википедия ) немного похоже на __fastcall, за исключением того, что оно передает первый параметр в eax, а eax также содержит возвращаемое значение. Это также очистка callee, но, поскольку мы не используем стек для чего-либо, кроме указателя возврата, нам не нужно ничего делать. Это позволяет нам избегать mov или xchg и просто использовать bswap напрямую.


bswap
Могу

@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 байтов.
Питер Ферри

@peterferrie Wow Я только что просматривал ваш сайт, читая о PE заголовках!
потолок кошка


6

Japt , 10 14 байтов

sG ùT8 ò w ¬nG

Попытайся


объяснение

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


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

@ETHproductions Я поддерживаю это; подслово &.в J делает это, и иногда это действительно полезно в гольфе. Однако кодирование во всех инверсиях может быть утомительным.
Коул

@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 байт?
Эрик Outgolfer

Оператор is недоступен в 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

Я заметил, что 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


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.
Эрик Outgolfer

@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
Arnauld


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 байт с помощью @ Neil

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 ... это короче?
Эрик 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

Преобразование в 4-значное основание 256, обратное преобразование цифр и преобразование обратно в десятичное число. В основном, выполните алгоритм, который предоставлен в OP. Возможно, в этот раз полезно, чтобы смешанное базовое преобразование 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. Для этой анонимной функции вы должны затем вставить свой ввод в ячейку A1 и приведенный выше код в непосредственное окно и нажать ввод
Тейлор Скотт

Да, и иногда VBA немного напуган (а версия для Mac гораздо хуже, чем версия для Windows), поэтому, и, если не указано иное, решения VBA предполагают 32-
Тейлор Скотт,

2

Сборка PPC (32-битная), 8 байтов

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

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

  • Соглашение о вызовах PPC помещает первый 32-битный параметр слова в SP + 24, а тени, которые обращаются в GPR3.
  • LWBRX принимает нагрузку GPR3 ​​(третий операнд) и расширяет его (второй операнд) в ноль, затем считывает 4 байта в обратном порядке и сохраняет его в GPR3 ​​(первый операнд).
  • GPR3 содержит возвращаемое значение.
  • BLR возвращается из функции (ответвляется по адресу в регистре LR)

К сожалению, нет никаких онлайн-эмуляторов сборки PPC, которые я мог бы продемонстрировать. Сожалею!


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^

Попробуйте ФБР онлайн!
Попробуйте 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 была короче!
Джузеппе

@ Джузеппе, ты собираешься поставить шляпу один, не так ли
MickyT

2

R , 41 байт

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

Попробуйте онлайн!

Проверьте все контрольные примеры!

Использует преобразование base-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 байтов.
Эрик Outgolfer

@EriktheOutgolfer Справедливо достаточно. Обновлен соответственно.
Арно

@EriktheOutgolfer Потому что 60 бит равны 7,5 байтов?
Джеппе Стиг Нильсен

@JeppeStigNielsen Это правда, но файл никогда не может быть длиной 7,5 байт, он будет пре- или пост-заполнен нулями.
Эрик Outgolfer

@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.Reverseinline, но этого не произошло (см. Альтернативу ниже).

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

Попробуйте онлайн!

Ungolfed:

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 байтов, преобразовать обратно в 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

Бонус:

19-байтовая версия в ОК, которую вы можете попробовать онлайн!

2/,/8#|12 8#(64#2)\
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.