Compare quatro números inteiros, retorne a palavra com base no máximo


9

Esta função deve ter quatro entradas inteiras ( a, b, c, d) e retornar uma palavra binária com base no qual os valores igualar o máximo de quatro.

O valor de retorno será entre 1e 0xF.

Por exemplo:

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

retorna 2(binário 0010; apenas o segundo bit menos significativo é definido, correspondendo ao bvalor máximo único)

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

retornos 0xC(binários 1100; 3º e 4º bits menos significativos configurados, correspondentes ce diguais ao valor máximo)

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

retorna 0xF(binário 1111; todos os quatro bits definidos porque todos os valores são iguais ao máximo)

Aqui está uma implementação simples:

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

O valor de retorno pode ser uma sequência de 0 e 1, vetor bool / bit ou número inteiro


2
Eu tenho uma solução em um idioma de golfe, que usa os built-in Reverse, Maximum, Equality-check, Join, Convert de binário em número inteiro, Converter de número inteiro em hexadecimal. Isso significa que minha pontuação é 1 devido à verificação de igualdade? Tenho a sensação de que isso é muito focada em linguagens regulares, e mesmo para aqueles que não é 100% claro o que o placar para deixou-nos dizer um máximo-builtin ..: S
Kevin Cruijssen

11
Eu sugiro que você tente: 1. alterar essa pergunta para code-golf, que se preocupa apenas com o número de bytes. 2. ou, restrinja a um determinado idioma (determinada versão do compilador / intérprete) e liste todas as instruções e operadores permitidos, e como classificá-las.
tsh

5
1 é uma opção melhor, IMO. Eu acho que isso faz um perfeitamente boa pergunta código-golfe e eu não posso ver qualquer benefício que viria de restringir os idiomas disponíveis para respostas
senox13

2
Atualizei minha pergunta para remover os critérios. Deixe-me saber que ainda não está claro
Sr. Anderson

5
Devo emitir um número decimal? Ou posso gerar 4 dígitos binários?
Tsh #

Respostas:


8

Geléia , 2 bytes

Toma entrada como [d,c,b,a]. Retorna uma lista de booleanos.

Ṁ=

Experimente online!

M aximum

= igual a (implica que o outro argumento é o argumento original; vetoriza)



4

APL (Dyalog Unicode) , SBCS de 4 bytes

Função de prefixo tácito anônimo. Toma [a,b,c,d]como argumento. Retorna uma matriz bit-booleana. *

⌈/=⌽

Experimente online!

⌈/ O máximo do argumento

= igual (vetoriza)

 o contrário do argumento?

* Observe que o APL armazena matrizes de booleanos usando um bit por valor; portanto, isso realmente retorna uma palavra de 4 bits, apesar da forma de exibição 0 0 1 0.



2

Perl 6 , 12 bytes

{$_ X==.max}

Experimente online!

Bloco de código anônimo que pega uma lista de números inteiros e retorna uma lista de booleanos. Se precisarmos retornar como um número, são +4 bytes para envolver o interior do bloco de código 2:[...].

Explicação:

{          }  # Anonymous code block
 $_           # With the input
    X==       # Which values are equal
       .max   # To the maximum element

O OP agora diz que você não precisa quebrar.
Adám 5/03/19

2

Japt, 5

m¶Urw

Tente!

-4 bytes graças a @Oliver!
-2 bytes graças a @Shaggy!

A entrada é uma matriz de 4 elementos no seguinte formato:

[d, c, b, a]

A saída é uma matriz de bits.


Claro que existe;) Aparentemente, existem muitos atalhos para aprender.
quer

Se uma matriz booleana é uma produção aceitável, este pode ser 7 bytes
Oliver

@Oliver, 5 bytes ;)
Shaggy

Vocês são muito bons :) É interessante como se rwconverte em r("w")reduz, obtendo repetidamente o máximo. O mesmo com a conversão para U.m("===", ...). De qualquer forma, obrigado pelas dicas!
quer

2

código de máquina x86 (MMX / SSE1), 26 bytes (4x int16_t)

código de máquina x86 (SSE4.1), 28 bytes (4x int32_t ou uint32_t)

código de máquina x86 (SSE2), 24 bytes (4x float32) ou 27B para cvt int32

(A última versão que converte int32 em float não é perfeitamente precisa para números inteiros grandes que arredondam para o mesmo float. Com a entrada float, o arredondamento é o problema do chamador e essa função funciona corretamente se não houver NaNs, identificando os floats que comparam == ao máximo. As versões inteiras funcionam para todas as entradas, tratando-as como um complemento assinado de 2.)

Tudo isso funciona no modo 16/32/64 bits com o mesmo código de máquina.

Uma convenção de chamada stack-args tornaria possível fazer um loop sobre os argumentos duas vezes (localizando max e depois comparando), possivelmente nos fornecendo uma implementação menor, mas ainda não tentei essa abordagem.

O x86 SIMD possui bitmap vetor-> inteiro como uma única instrução ( pmovmskbou movmskpspd); portanto, era natural para isso, embora as instruções MMX / SSE tenham pelo menos 3 bytes de comprimento. As instruções SSSE3 e posteriores são mais longas que SSE2 e as instruções MMX / SSE1 são as mais curtas. Versões diferentes de pmax*(máximo vertical inteiro compactado) foram introduzidas em momentos diferentes, com SSE1 (para mmx regs) e SSE2 (para xmm regs) tendo apenas palavra assinada (16 bits) e byte não assinado.

( pshufwe pmaxswnos registros MMX são novos no Katmai Pentium III, eles realmente requerem SSE1, não apenas o bit de recurso da CPU MMX.)

É possível chamar a partir de C, como unsigned max4_mmx(__m64)no i386 System V ABI, que passa um __m64argumento mm0. (Não x86-64 System V, que passa __m64em 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

Se houvesse um pmovmskw, o que teria salvo o packsswbe o and(3 + 2 bytes). Não precisamos, and eax, 0x0fporque pmovmskbem um registrador MMX já zeros os bytes superiores. Os registros MMX têm apenas 8 bytes de largura, portanto, o AL de 8 bits cobre todos os bits diferentes de zero possíveis.

Se soubéssemos que nossas entradas não eram negativas, poderíamospacksswb mm1, mm0 produzir bytes assinados não negativos nos 4 bytes superiores de mm1, evitando a necessidade de anddepois pmovmskb. Assim, 24 bytes.

O pacote x86 com saturação assinada trata a entrada e a saída como assinadas, preservando sempre o bit de sinal. ( https://www.felixcloutier.com/x86/packsswb:packssdw ). Curiosidade: o pacote x86 com saturação não assinada ainda trata a entrada como assinada. Talvez por isso PACKUSDWnão tenha sido introduzido até o SSE4.1, enquanto as outras três combinações de tamanho e assinatura existiam desde o MMX / SSE2.


Ou com números inteiros de 32 bits em um registro XMM (e em pshufdvez de pshufw), todas as instruções precisariam de mais um byte de prefixo, exceto para movmskpssubstituir o pacote / e. Mas pmaxsd/ pmaxudpreciso de um byte extra extra ...

pode ser chamado de C comounsigned max4_sse4(__m128i); no x86-64 System V ou MSVC vectorcall ( -Gv), sendo que ambos passam __m128i/ __m128d/ __m128args nos registros XMM começando com 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

Ou, se aceitarmos a entrada como float, podemos usar as instruções SSE1. O floatformato pode representar uma ampla gama de valores inteiros ...

Ou se você acha que isso está distorcendo as regras demais, comece com 3 bytes 0F 5B C0 cvtdq2ps xmm0, xmm0para converter, criando uma função de 27 bytes que funciona para todos os números inteiros que são exatamente representáveis ​​como IEEE binary32 floate muitas combinações de entradas nas quais algumas das entradas são obtidas . arredondado para um múltiplo de 2, 4, 8 ou o que for durante a conversão. (Portanto, é 1 byte menor que a versão SSE4.1 e funciona em qualquer x86-64 com apenas SSE2.)

Se alguma das entradas flutuantes for NaN, observe que é maxps a,bimplementado exatamente (a<b) ? a : b, mantendo o elemento do 2º operando em desordenado . Portanto, pode ser possível retornar com um bitmap diferente de zero, mesmo que a entrada contenha algum NaN, dependendo de onde estejam.

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

copiar e shuffle com pshufdainda é nossa melhor aposta: shufps dst,src,imm8lê a entrada para a metade baixa dst da dst . E precisamos de uma cópia e reprodução aleatória não destrutiva as duas vezes, para que 3 bytes movhlpse unpckhps/ pd estejam fora. Se reduzíssemos a um máximo escalar, poderíamos usá-lo, mas custa outra instrução para transmitir antes da comparação, se ainda não tivermos o máximo em todos os elementos.


Relacionado: O SSE4.1 phminposuwpode encontrar a posição e o valor do mínimo uint16_tem um registro XMM. Eu não acho que é uma vitória subtrair do 65535 para usá-lo no máximo, mas veja uma resposta SO sobre como usá-lo para o máximo de bytes ou números inteiros assinados.


1

Python 3.8 (pré-lançamento) , 67 bytes

A função Lambda, que recebe 4 números inteiros, muda o resultado booleano da comparação para o valor máximo com alguma ajuda do novo operador de atribuição do Python 3.8 e retorna o OR bit a bit dos resultados

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

Experimente online!


: = lembra-me dos velhos tempos em que esse era o operador de atribuição com a fórmula do Lotus Notes. Acho que vou ter que dar uma olhada em 3,8 por vezes velho amor :)
ElPedro



1

JavaScript (ES6), 30 bytes

Toma entrada como ([d,c,b,a]). Retorna 4 valores booleanos.

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

Experimente online!


11
O OP esclareceu que você pode realmente retornar 4 valores booleanos.
Adám 5/03/19


1

Python 3 , 59 bytes 66 bytes

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

Experimente online!

Aceita entrada como [a,b,c,d] e gera uma lista de booleanos.

Editado para ser uma função adequada, em seguida, salvou 2 bytes removendo colchetes ao redor do condicional.


11
Olá e bem-vindo ao PPCG. Tal como está, sua resposta tem a forma de um trecho, que não é permitido. Corrija sua resposta para estar em conformidade com nosso consenso de E / S , ou seja, torne-a uma função ou um programa completo.
Jonathan Frech

11
Editado. Primeira vez. Aprecie a atenção!
Bsoned

Você pode reduzi-lo para 37 bytes usando a compreensão dessa lista em um lambda. Bem-vindo ao PPCG, e aproveite a sua estadia!
Value Ink

@ValueInk A remoção do espaço em branco supérfluo economiza mais um byte.
Jonathan Frech

1

1. Python 3.5, 90 bytes

Toma sequência de números como parâmetros. Retorna a string "binária"

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

exemplo:

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

Explicação

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 # (compilador interativo do Visual C #) , 26 bytes

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

Experimente online!

Recebe entrada no formato [d,c,b,a]. Todos os outros abaixo recebem informações como[a,b,c,d]

C # (compilador interativo do Visual C #) , 35 bytes

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

Retorna um IEnumerable<bool>.

Experimente online!

C # (compilador interativo do Visual C #) , 39 bytes

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

Retorna um IEnumerable<int>, que representa bits.

Experimente online!

C # (compilador interativo do Visual C #) , 49 bytes

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

Imprime uma string binária em STDOUT.

Experimente online!


IEnumerable<bool> é aceitável.
Adám 5/03/19

0

PHP, 54 bytes

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

ou

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

receba entrada dos argumentos da linha de comando. Corra com -nrou experimente-os online .


0

Aqui está uma versão JS que sai como binária

update: Mais curto com junção e sem a pesquisa:

JavaScript (Node.js) , 42 bytes

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

Experimente online!

Anterior, com pesquisa, 49 bytes

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

Experimente online!

Anterior, com redução, 52 bytes:

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

Experimente online!

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


11
[0,1][...]0 01 1

@ Arnauld parece óbvio agora. Obrigado!
Pureferret 4/03/19

0

C # (compilador interativo do Visual C #) , 51 bytes

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

Experimente online!

Acima está uma função anônima que sai modificando um argumento . A saída é uma matriz de 1 e 0.

Abaixo está uma função recursiva que gera um número inteiro.

C # (compilador interativo do Visual C #) , 60 bytes

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

Experimente online!

Ambas as funções recebem entrada como uma matriz de 4 elementos.

[d, c, b, a]

Você não precisa produzir um número inteiro.
Adám 5/03/19

@ Adam - obrigado :) Eu percebi isso depois de postar enquanto eu estava trabalhando na minha outra resposta. Antes que eu tivesse chance de mudar, havia outra resposta em C # que usava muitos dos bons truques.
dana



0

Lote, 92 bytes

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

Recebe argumentos como parâmetros de linha de comando na ordem inversa. Funciona calculando aritmeticamente o máximo dos parâmetros, reduzindo-os e adicionando apenas diferenças positivas do máximo em execução e, em seguida, mapeando cada parâmetro novamente desta vez, comparando-o ao máximo. Convenientemente cmd/cset/anão gera uma nova linha, portanto os resultados são automaticamente concatenados juntos. O %f%simplesmente salva 5 bytes no que seria uma construção repetida.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.