Сравните четыре целых числа, верните слово на основе максимума

9

Эта функция должна принимать четыре целых входа ( a, b, c, d) и возвращает двоичное слово , на основании которых значения равны максимум четыре.

Возвращаемое значение будет между 1и 0xF.

Например:

a = 6, b = 77, c = 1, d = 4

возвращает 2(двоичный 0010; устанавливается только 2-й младший значащий бит, соответствующий bединственному максимальному значению)

a = 4, b = 5, c = 10, d = 10

возвраты 0xC(двоичные 1100; биты младших и младших разрядов 3-й и 4-й установлены в соответствии с максимальным значением cи dравны ему)

a = 1, b = 1, c = 1, d = 1

возвращает 0xF(двоичный код 1111; все четыре бита установлены, поскольку все значения равны максимальному)

Вот простая реализация:

int getWord(int a, int b, int c, int d)
{
    int max = a;
    int word = 1;
    if (b > max)
    {
        max = b;
        word = 2;
    }
    else if (b == max)
    {
        word |= 2;
    }
    if (c > max)
    {
        max = c;
        word = 4;
    }
    else if (c == max)
    {
        word |= 4;
    }
    if (d > max)
    {
        word = 8;
    }
    else if (d == max)
    {
        word |= 8;
    }
    return word;
}

возвращаемое значение может быть строкой 0 и 1, вектором bool / bit или целым числом

Мистер андерсон
источник
2
У меня есть решение на языке игры в гольф, в котором используются встроенные функции: обратное, максимальное, проверка на равенство, объединение, преобразование из двоичного в целое, преобразование из целого в шестнадцатеричное. Означает ли это, что мой результат равен 1 из-за проверки на равенство? У меня такое ощущение, что это слишком сильно ориентировано на обычные языки, и даже для тех, кто не на 100% ясно, что за
оценка
1
Я бы посоветовал вам попытаться: 1. изменить этот вопрос на код-гольф, который заботится только о количестве байтов. 2. или, ограничивайтесь определенным языком (определенная версия компилятора / интерпретатора, пожалуйста), и перечислите все допустимые операторы и операторы, а также способы их оценки.
TSH
5
1 - лучший вариант, ИМО. Я думаю, что это очень хороший вопрос для игры в гольф, и я не вижу никакой выгоды от ограничения языков, доступных для ответов
senox13
2
Я обновил свой вопрос, чтобы удалить критерии. Дайте мне знать, что это все еще неясно
г-н Андерсон
5
Должен ли я выводить десятичное число? Или я могу вместо этого вывести 4 двоичные цифры?
TSH

Ответы:

8

Желе , 2 байта

Принимает вход как [d,c,b,a]. Возвращает список логических значений.

Ṁ=

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

M aximum

= равно (подразумевает, что другой аргумент является исходным аргументом; векторизация)

Адам
источник
5

R , 17 байт

max(a<-scan())==a

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

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

R , 33 байта

sum(2^which(max(a<-scan())==a)/2)

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

Кирилл Л.
источник
4

APL (Dyalog Unicode) , 4 байта SBCS

Функция анонимного молчаливого префикса. Принимает в [a,b,c,d]качестве аргумента. Возвращает битовый логический массив. *

⌈/=⌽

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

⌈/ Максимум аргумента

= равный (векторизация)

 обратная сторона аргумента?

* Обратите внимание, что APL хранит массивы логических значений, используя один бит на значение, так что это действительно возвращает 4-битное слово, несмотря на то, что форма отображения 0 0 1 0.

Адам
источник
3

Haskell , 20 18 байтов

2 байта сохранены благодаря гордому haskeller

map=<<(==).maximum

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

Специальный охотник за гарфами
источник
Вы можете вывести строку.
Адам
1
Запись mapвместо (<$>)будет на два байта короче!
гордый haskeller
@proudhaskeller Хороший улов. Не могу поверить, что я этого не видел.
Ad Hoc
2

Perl 6 , 12 байт

{$_ X==.max}

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

Блок анонимного кода, который принимает список целых чисел и возвращает список логических значений. Если нам нужно вернуть как число, это +4 байта, чтобы обернуть внутреннюю часть блока кода 2:[...].

Объяснение:

{          }  # Anonymous code block
 $_           # With the input
    X==       # Which values are equal
       .max   # To the maximum element
Джо Кинг
источник
ОП сейчас говорит, что вам не нужно оборачиваться.
Адам
2

Джапт, 5

m¶Urw

Попробуй это!

-4 байта благодаря @Oliver!
-2 байта благодаря @Shaggy!

Input представляет собой массив из 4 элементов в следующем формате:

[d, c, b, a]

Вывод представляет собой массив битов.

Dana
источник
Конечно, есть;) Есть, вероятно, много ярлыков для изучения.
Dana
Если логический массив является приемлемым выводом, это может быть 7 байтов
Оливер
@Oliver, 5 байт ;)
Лохматый
Вы, ребята, довольно хороши :) Интересно, как rwпреобразуется в r("w")сокращение, постоянно получая максимум. То же самое с превращением в U.m("===", ...). В любом случае спасибо за советы!
Dana
2

машинный код x86 (MMX / SSE1), 26 байт (4x int16_t)

машинный код x86 (SSE4.1), 28 байт (4x int32_t или uint32_t)

машинный код x86 (SSE2), 24 байта (4x float32) или 27B для cvt int32

(Последняя версия, которая конвертирует int32 в число с плавающей точкой, не совсем точна для больших целых чисел, округляющих до одного и того же числа с плавающей запятой. При вводе с плавающей точкой округление является проблемой вызывающей стороны, и эта функция работает правильно, если нет NaN, идентифицируя числа с плавающей запятой, которые сравнивают == до максимума. Целочисленные версии работают для всех входных данных, рассматривая их как дополнение к знаку 2.)

Все они работают в 16/32/64-битном режиме с одинаковым машинным кодом.

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

x86 SIMD имеет вектор-> целочисленное растровое изображение в виде одной инструкции (pmovmskb или movmskpsили pd), поэтому это было естественно для этого, даже если инструкции MMX / SSE имеют длину не менее 3 байтов. SSSE3 и более поздние инструкции длиннее, чем SSE2, а MMX / SSE1 - самые короткие. Различные версии pmax*(максимум упакованного целого по вертикали) были представлены в разное время, причем SSE1 (для регистров mmx) и SSE2 (для регистров xmm) имели только знаковое слово (16-битное) и байт без знака.

( pshufwи pmaxswв MMX регистры являются новыми с Katmai Pentium III, поэтому на самом деле они требуют SSE1, а не только бит функции MMX CPU).

Это вызывается из C, как unsigned max4_mmx(__m64)и для i386 System V ABI, который передает __m64аргумент mm0. (Не x86-64 System V, которая проходит__m64 в xmm0!)

   line         code bytes
    num  addr   
     1                         global max4_mmx
     2                             ;; Input 4x int16_t in mm0
     3                             ;; output: bitmap in EAX
     4                             ;; clobbers: mm1, mm2
     5                         max4_mmx:
     6 00000000 0F70C8B1           pshufw    mm1, mm0, 0b10110001   ; swap adjacent pairs
     7 00000004 0FEEC8             pmaxsw    mm1, mm0
     8                         
     9 00000007 0F70D14E           pshufw    mm2, mm1, 0b01001110   ; swap high/low halves
    10 0000000B 0FEECA             pmaxsw    mm1, mm2
    11                         
    12 0000000E 0F75C8             pcmpeqw   mm1, mm0               ; 0 / -1
    13 00000011 0F63C9             packsswb  mm1, mm1               ; squish word elements to bytes, preserving sign bit
    14                         
    15 00000014 0FD7C1             pmovmskb  eax, mm1          ; extract the high bit of each byte
    16 00000017 240F               and       al, 0x0F          ; zero out the 2nd copy of the bitmap in the high nibble
    17 00000019 C3                 ret

size = 0x1A = 26 bytes

Если бы был pmovmskw, что бы спаслоpacksswb и и and(3 + 2 байта). Нам не нужно, and eax, 0x0fпотому что pmovmskbв регистре MMX уже нули старшие байты. Регистры MMX имеют ширину всего 8 байтов, поэтому 8-битный AL охватывает все возможные ненулевые биты.

Если бы мы знали, что наши входные данные были неотрицательными, мы моглиpacksswb mm1, mm0 бы производить неотрицательные подписанные байты в верхних 4 байтах mm1, избегая необходимости andпосле pmovmskb. Таким образом, 24 байта.

Пакет x86 с насыщением со знаком обрабатывает ввод и вывод как подписанный, поэтому он всегда сохраняет знаковый бит. ( https://www.felixcloutier.com/x86/packsswb:packssdw ). Интересный факт: пакет x86 с насыщением без знака все еще обрабатывает ввод как подписанный. Это может быть причиной того, что PACKUSDWне было введено до SSE4.1, в то время как другие 3 комбинации размера и подписи существовали со времен MMX / SSE2.


Или с 32-разрядными целыми числами в регистре XMM (и pshufdвместо pshufw) каждой инструкции потребуется еще один байт префикса, за исключением movmskpsзамены пакета / и. Но pmaxsd/pmaxud нужен дополнительный дополнительный байт ...

вызывается из C, какunsigned max4_sse4(__m128i); и в x86-64 System V, или в MSVC vectorcall ( -Gv), оба из которых передают __m128i/ __m128d/ __m128args в регистрах XMM, начиная с xmm0.

    20                         global max4_sse4
    21                             ;; Input 4x int32_t in xmm0
    22                             ;; output: bitmap in EAX
    23                             ;; clobbers: xmm1, xmm2
    24                         max4_sse4:
    25 00000020 660F70C8B1         pshufd    xmm1, xmm0, 0b10110001   ; swap adjacent pairs
    26 00000025 660F383DC8         pmaxsd    xmm1, xmm0
    27                         
    28 0000002A 660F70D14E         pshufd    xmm2, xmm1, 0b01001110   ; swap high/low halves
    29 0000002F 660F383DCA         pmaxsd    xmm1, xmm2
    30                         
    31 00000034 660F76C8           pcmpeqd   xmm1, xmm0               ; 0 / -1
    32                         
    33 00000038 0F50C1             movmskps  eax, xmm1          ; extract the high bit of each dword
    34 0000003B C3                 ret

size = 0x3C - 0x20 = 28 bytes

Или, если мы принимаем ввод как float, мы можем использовать инструкции SSE1. floatФормат может представлять собой широкий диапазон целочисленных значений ...

Или, если вы думаете, что это слишком сильно 0F 5B C0 cvtdq2ps xmm0, xmm0нарушает правила, начните с 3-байтового преобразования, создав 27-байтовую функцию, которая работает для всех целых чисел, которые точно представлены в виде двоичного кода IEEE32float , и многих комбинаций входных данных, где некоторые входные данные получают округляется до кратного 2, 4, 8 или любого другого значения во время преобразования. (Таким образом, он на 1 байт меньше, чем версия SSE4.1, и работает на любом x86-64 только с SSE2.)

Если какой-либо из входных данных с плавающей запятой равен NaN, обратите внимание, что он maxps a,bточно реализуется (a<b) ? a : b, сохраняя элемент из второго операнда в неупорядоченном виде . Таким образом, для этого может быть возможно возвращение с ненулевым растровым изображением, даже если вход содержит некоторое NaN, в зависимости от того, где они находятся.

unsigned max4_sse2(__m128);

    37                         global max4_sse2
    38                             ;; Input 4x float32 in xmm0
    39                             ;; output: bitmap in EAX
    40                             ;; clobbers: xmm1, xmm2
    41                         max4_sse2:
    42                         ;    cvtdq2ps  xmm0, xmm0
    43 00000040 660F70C8B1         pshufd    xmm1, xmm0, 0b10110001   ; swap adjacent pairs
    44 00000045 0F5FC8             maxps     xmm1, xmm0
    45                         
    46 00000048 660F70D14E         pshufd    xmm2, xmm1, 0b01001110   ; swap high/low halves
    47 0000004D 0F5FCA             maxps     xmm1, xmm2
    48                         
    49 00000050 0FC2C800           cmpeqps   xmm1, xmm0               ; 0 / -1
    50                         
    51 00000054 0F50C1             movmskps  eax, xmm1          ; extract the high bit of each dword
    52 00000057 C3                 ret

size = 0x58 - 0x40 = 24 bytes

copy-and-shuffle с pshufd- все еще наша лучшая ставка: shufps dst,src,imm8считывает ввод для нижней половины dst из dst . И нам нужно неразрушающее копирование и перемешивание оба раза, так что 3-байт movhlpsиunpckhps / pd оба отсутствуют. Если бы мы сужались до скалярного максимума, мы могли бы использовать их, но для трансляции перед сравнением стоит другая инструкция, если у нас уже нет максимума во всех элементах.


Связано: SSE4.1 phminposuwможет найти положение и значение минимума uint16_tв регистре XMM. Я не думаю, что было бы выгодно вычесть из 65535, чтобы использовать его для max, но вижу SO-ответ об использовании его для max байтов или целых чисел со знаком.

Питер Кордес
источник
1

Python 3.8 (предварительная версия) , 67 байт

Лямбда-функция, которая принимает 4 целых числа, немного сдвигает логический результат их сравнения до максимального значения с помощью нового оператора присваивания в Python 3.8 и возвращает побитовое ИЛИ результатов

lambda a,b,c,d:((m:=max(a,b,c,d))==d)<<3|(m==c)<<2|(m==b)<<2|(a==m)

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

senox13
источник
: = напоминает мне о старых временах, когда это был оператор присваивания с формулой Lotus Notes. Думаю, мне придется взглянуть на 3.8 для старых времен :)
ElPedro
1

05AB1E , 3 2 байта

ZQ

Ввод в виде списка [d,c,b,a], вывод в виде списка логических.

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

Z    # Take the maximum of the implicit input-list
 Q   # Check for each in the (implicit) input-list if it equals this value
     # (and output implicitly as result)
Кевин Круйссен
источник
ОП был обновлен - вам не нужно конвертировать в гекс.
Адам
1

JavaScript (ES6), 30 байт

Принимает вход как ([d,c,b,a]). Возвращает 4 логических значения.

a=>a.map(x=>x==Math.max(...a))

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

Arnauld
источник
1
ОП пояснил, что вы действительно можете вернуть 4 логических значения.
Адам
1

Python 3 , 59 байт, 66 байт

def f(l):
 n=max(a)
 for i in 0,1,2,3:a[i]=a[i]==n
 return a[::-1]

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

Принимает ввод как [a,b,c,d]и выводит список логических значений.

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

Bsoned
источник
1
Привет и добро пожаловать в PPCG. В своем нынешнем виде ваш ответ имеет форму фрагмента, который запрещен. Пожалуйста, исправьте свой ответ, чтобы он соответствовал нашему консенсусу ввода / вывода , т.е. сделайте его функцией или полной программой.
Джонатан Фрех
1
Ред. Первый раз Цените головы!
Bsoned
Вы можете уменьшить его до 37 байт, используя это понимание списка в лямбде. Добро пожаловать в PPCG и приятного пребывания!
Value Ink
@ValueInk Удаление лишних пробелов сохраняет еще один байт.
Джонатан Фрех
1

1. Python 3.5, 90 байт

Принимает последовательность чисел в качестве параметров. Возвращает "двоичную" строку

import sys;v=[*map(int,sys.argv[1:])];m=max(v);s=""
for e in v:s=str(int(e==m))+s
print(s)

пример:

$ ./script.py 6 77 1 4 77
10010

объяснение

import sys
# convert list of string parameters to list of integers
v=[*map(int,sys.argv[1:])]
# get max
m=max(v)
# init outstring
s=""
# walk through list
for e in v:
    # prepend to outstring: int(True)=>1, int(False)=>0
    s=str(int(e==m))+s
# print out result
print(s)
Rene
источник
1

C # (интерактивный компилятор Visual C #) , 26 байт

n=>n.Select(a=>a==n.Max())

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

Принимает ввод в формате [d,c,b,a]. Все остальные внизу воспринимают как[a,b,c,d]

C # (интерактивный компилятор Visual C #) , 35 байт

n=>n.Select((a,b)=>n[3-b]==n.Max())

Возвращает IEnumerable<bool>.

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

C # (интерактивный компилятор Visual C #) , 39 байт

n=>n.Select((a,b)=>n[3-b]==n.Max()?1:0)

Возвращает IEnumerable<int>, которые представляют биты.

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

C # (интерактивный компилятор Visual C #) , 49 байт

n=>{for(int i=4;i-->0;Write(n[i]==n.Max()?1:0));}

Печатает двоичную строку в STDOUT.

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

Воплощение невежества
источник
IEnumerable<bool> является приемлемым.
Адам
0

PHP, 54 байта

while($i<4)$argv[++$i]<max($argv)||$r+=1<<$i-1;echo$r;

или

while($i<4)$argv[++$i]<max($argv)||$r+=1<<$i;echo$r/2;

принимать входные данные из аргументов командной строки. Запустите -nrили попробуйте их онлайн .

Titus
источник
0

Вот версия JS, которая выводит как двоичный файл

обновление: короче с объединением и без поиска:

JavaScript (Node.js) , 42 байта

a=>a.map(x=>+(x==Math.max(...a))).join('')

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

Предыдущая, с поиском, 49 байтов

a=>a.map(x=>[0,1][+(x==Math.max(...a))]).join('')

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

Предыдущий, с уменьшением, 52 байта:

a=>a.reduce((y,x)=>y+[0,1][+(x==Math.max(...a))],'')

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

fa=>a.map(x=>+(x==Math.max(...a))).join('')
console.log(f([ 4, 1,77, 6])) // 0010
console.log(f([10,10, 5, 4])) // 1100
console.log(f([ 1, 1, 1, 1])) // 1111

Pureferret
источник
1
Вы можете безопасно удалить, [0,1][...]так как вы используете индекс, который уже0 или 1,
Арно
@ Arnauld теперь кажется очевидным. Спасибо!
Pureferret
0

C # (интерактивный компилятор Visual C #) , 51 байт

x=>{for(int m=x.Max(),i=4;i-->0;)x[i]=x[i]==m?1:0;}

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

Выше приведена анонимная функция, которая выводит путем изменения аргумента . Вывод представляет собой массив из 1 и 0.

Ниже приведена рекурсивная функция, которая выводит целое число.

C # (интерактивный компилятор Visual C #) , 60 байт

int f(int[]x,int i=3)=>i<0?0:2*f(x,i-1)|(x[i]==x.Max()?1:0);

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

Обе функции принимают входные данные как массив из 4 элементов.

[d, c, b, a]
Dana
источник
Вам не нужно выводить целое число.
Адам
@ Adam - спасибо :) Я понял это после публикации, когда я работал над другим ответом. До того, как у меня появилась возможность измениться, был еще один ответ на C #, в котором использовалось много хороших трюков.
Dana
0

Python 3 , 42 байта

f=lambda a:list(map(lambda x:x==max(a),a))

Просто возвращает список того, является ли элемент максимальным для каждого элемента на входе. -2 байта, если вы не считаете f=назначение.

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

ThePlasmaRailgun
источник
f=не учитывается, за исключением рекурсивных функций
только ASCII
0

Пакет, 92 байта

@set m=%1
@set f=@for %%i in (%*)do @
%f%set/a"m=m+(m-=%%i)*(m>>31)
%f%cmd/cset/a!(m-%%i)

Принимает аргументы в качестве параметров командной строки в обратном порядке. Работает, арифметически вычисляя максимум параметров, уменьшая их и добавляя только положительные отличия от рабочего максимума, а затем снова сопоставляя каждый параметр, сравнивая его с максимумом. Удобно cmd/cset/aне выводить новую строку, поэтому результаты автоматически объединяются вместе. %f%Просто сохраняет 5 байт на то , что будет повторена конструкция.

Нил
источник