Порівняйте чотири цілі числа, поверніть слово на основі максимуму


9

Ця функція повинна приймати чотири цілих входу ( a, b, c, d) і повертає бінарне слово , на підставі яких значення рівні максимум чотири.

Повернене значення буде між 1і 0xF.

Наприклад:

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

повертає 2(двійкові 0010; встановлюється лише другий найменш значущий біт, що відповідає 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 / біт або ціле число


2
У мене є рішення мовою для гольфу, яка використовує вбудовані Зворотний, Максимум, Перевірка рівності, Приєднатися, Перетворити з двійкового на ціле число, Перетворити з цілого на шістнадцятковий. Чи означає це, що моя оцінка 1 за рахунок перевірки рівності? У мене таке відчуття, що це занадто сильно зосереджено на звичайних мовах, і навіть для тих, хто не на 100% зрозумілий, який бал за скажімо, Максимально вбудований ..: S
Кевін Круїйсен

1
Я б запропонував вам спробувати: 1. змінити це питання на код-гольф, який хвилює лише кількість байтів. 2. або, обмежтесь якоюсь певною мовою (будь-яка версія компілятора / інтерпретатора будь ласка), і перерахуйте всі дозволені оператори та оператори та спосіб їх оцінки.
TSH

5
1 - кращий варіант, ІМО. Я думаю, що це ставить ідеально хороше питання щодо коду-гольфу, і я не бачу жодної користі від обмеження доступних мов для відповідей
senox13

2
Я оновив своє запитання, щоб видалити критерії. Дайте мені знати, що це все ще незрозуміло
містер Андерсон

5
Чи слід виводити десяткове число? Або я можу натомість вивести 4 двійкові цифри?
TSH

Відповіді:


8

Желе , 2 байти

Вводиться як " [d,c,b,a]. Повертає список булів.

Ṁ=

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

М аксіміст

= дорівнює (мається на увазі, що інший аргумент є оригінальним аргументом; векторизація)



4

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

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

⌈/=⌽

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

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

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

 зворотний аргумент?

* Зауважте, що APL зберігає масиви Booleans, використовуючи один біт на значення, тому це дійсно повертає 4-бітове слово, незважаючи на те, що форма відображення 0 0 1 0.


3

Haskell , 20 18 байт

2 байти збережено завдяки гордому хасклеру

map=<<(==).maximum

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


Ви можете вивести рядок.
Адам

1
Написання mapзамість (<$>)буде на два байти коротше!
гордий haskeller

@proudhaskeller Хороший улов. Не можу повірити, що я цього не бачив.
Спеціальний мисливець на

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!

Вхід - це 4-елементний масив у такому форматі:

[d, c, b, a]

Вихід - це масив бітів.


Звичайно, є;) Явно є багато ярликів, щоб навчитися.
Dana

Якщо булівський масив є прийнятним результатом, це може бути 7 байт
Олівер

@Oliver, 5 байт ;)
Shaggy

Ви, хлопці, дуже хороші :) Цікаво, як rwперетворює на r("w")зменшення, багаторазово отримуючи макс. Те саме з перетворенням на U.m("===", ...). У будь-якому випадку, дякую за поради!
Dana

2

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

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

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

(Остання версія, яка перетворює int32 у плаваючий, не є абсолютно точною для великих цілих чисел, які округляються до одного плаваючого елемента. З введенням поплавця округлення є проблемою виклику, і ця функція працює правильно, якщо немає NaN, ідентифікуючи поплавці, які порівнюють == до максимуму цілі версії працюють для всіх входів, трактуючи їх як підписані доповнення 2.)

Усі вони працюють в 16/32/64-бітному режимі з тим же машинним кодом.

Конвенція, що викликає стеки, дає змогу двічі перебирати аргументи (знаходячи макс, а потім порівнюючи), можливо, даючи нам меншу реалізацію, але я не пробував такого підходу.

x86 SIMD має векторні> цілісні растрові карти як єдину інструкцію ( pmovmskbабо movmskpspd), тому це було природно, навіть якщо інструкції MMX / SSE мають принаймні 3 байти. Інструкції SSSE3 та новіших версій довші, ніж SSE2, а інструкції MMX / SSE1 - найкоротші. Різні версії pmax*(пакували цілочисельні вертикальні максимуми) були введені в різний час, при цьому SSE1 (для regx mmx) і SSE2 (для xmm reg) мали лише підписане слово (16-бітне) та непідписаний байт.

( pshufwа pmaxswрегістри MMX є новими в Katmai Pentium III, тому вони дійсно потребують SSE1, а не лише біт функції процесора MMX.)

Це можна викликати з C, як unsigned max4_mmx(__m64)у системі i386 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/ __m128арг в 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Формат може являти собою широкий діапазон цілочисельних значень ...

Або якщо ви вважаєте, що це загинає правила занадто далеко, почніть з 3-байтового 0F 5B C0 cvtdq2ps xmm0, xmm0перетворення, зробивши 27-байтну функцію, яка працює для всіх цілих чисел, які точно представлені як IEEE binary32 float, і багатьох комбінацій входів, де деякі входи отримують округлене до кратного 2, 4, 8 або будь-якого іншого під час перетворення. (Отже, це на 1 байт менше, ніж версія SSE4.1, і працює на будь-якому x86-64 лише з SSE2.)

Якщо будь-який з поплавкових входів є NaN, зауважте, що він maxps a,bточно реалізує (a<b) ? a : b, зберігаючи елемент від 2-го операнда не упорядкованим . Таким чином, можливо, це може повернутися з ненульовою растровою картою, навіть якщо вхід містить деякий 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

копіювати і перетасовувати з 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)

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


: = нагадує мене про старі часи, коли це був оператор призначення з формулою 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

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 байти, видаливши дужки навколо умовного.


1
Привіт і ласкаво просимо до PPCG. На даний момент ваша відповідь має форму фрагмента, який заборонено. Будь ласка, виправте свою відповідь, щоб вона відповідала нашому консенсусу вводу / виводу , тобто зробіть це функцією або повною програмою.
Джонатан

1
Відредаговано. Перший раз навколо. Цінуйте голови вгору!
Бсонірований

Ви можете зменшити його до 37 байт, використовуючи це розуміння списку в межах лямбда. Ласкаво просимо до PPCG та насолоджуємось своїм перебуванням!
Значення чорнила

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

1

C # (Visual C # Interactive Compiler) , 26 байт

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

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

Здійснює введення у форматі [d,c,b,a]. Усі інші, представлені нижче, приймають дані як[a,b,c,d]

C # (Visual C # Interactive Compiler) , 35 байт

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

Повертає IEnumerable<bool>.

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

C # (Visual C # Interactive Compiler) , 39 байт

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

Повертає ан IEnumerable<int>, які представляють біти.

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

C # (Visual C # Interactive Compiler) , 49 байт

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

Друкує двійковий рядок до STDOUT.

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


IEnumerable<bool> є прийнятним.
Адам


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


1
Ви можете безпечно видалити, [0,1][...]оскільки ви використовуєте індекс, який вже є0 або 1.
Арнольд

@Arnauld здається очевидним зараз. Дякую!
Pureferret

0

C # (Visual C # Interactive Compiler) , 51 байт

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

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

Вище - анонімна функція, яка виводиться шляхом зміни аргументу . Вихід - це масив від 1 до 0.

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

C # (Visual C # Interactive Compiler) , 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]

Вам не потрібно виводити ціле число.
Адам

@Adam - спасибі :) Я зрозумів це після публікації, коли працював над своєю іншою відповіддю. Перш ніж у мене був шанс змінитись, з’явилася ще одна відповідь C #, яка використовувала багато хороших хитрощів.
Dana



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 байт на те , що буде повторена конструкція.

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