Compare cuatro enteros, devuelva la palabra según el máximo


9

Esta función debe tomar cuatro entradas enteros ( a, b, c, d) y devolver una palabra binaria basan en la que los valores son iguales a la máxima de la cuatro.

El valor de retorno estará entre 1y 0xF.

Por ejemplo:

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

retornos 2(binario 0010; solo se establece el segundo bit menos significativo correspondiente a bser el único valor máximo)

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

retornos 0xC(binario 1100; 3º y 4º conjunto de bits menos significativos correspondientes ce diguales al valor máximo)

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

retornos 0xF(binario 1111; los cuatro bits establecidos porque todos los valores son iguales al máximo)

Aquí hay una implementación simple:

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

el valor de retorno puede ser una cadena de 0 y 1, un vector bool / bit o un entero


2
Tengo una solución en un lenguaje de golf, que utiliza los valores incorporados Reverse, Maximum, Equality-check, Join, Convert from binary to integer, Convert from integer to hexadecimal. ¿Esto significa que mi puntaje es 1 debido a la verificación de igualdad? Tengo la sensación de que esto está demasiado enfocado en los idiomas regulares, e incluso para aquellos que no están 100% claros para qué puntaje, digamos un máximo incorporado ...: S
Kevin Cruijssen

1
Le sugiero que intente: 1. cambiar esta pregunta a code-golf, que solo se preocupa por la cantidad de bytes. 2. o, restringir a cierto idioma (cierta versión del compilador / intérprete, por favor), y enumerar todas las declaraciones y operadores permitidos, y cómo calificarlos.
tsh

55
1 es una mejor opción, OMI. Creo que esta es una pregunta de código de golf perfectamente buena y no puedo ver ningún beneficio que resultaría de restringir los idiomas disponibles para las respuestas
senox13

2
Actualicé mi pregunta para eliminar los criterios. Avíseme si aún no está claro
Sr. Anderson el

55
¿Debo mostrar un número decimal? ¿O puedo generar 4 dígitos binarios en su lugar?
tsh

Respuestas:


8

Jalea , 2 bytes

Toma entrada como [d,c,b,a]. Devuelve una lista de booleanos.

Ṁ=

Pruébalo en línea!

M Aximum

= igual a (implica que el otro argumento es el argumento original; vectorises)



4

APL (Dyalog Unicode) , SBCS de 4 bytes

Función de prefijo tácito anónimo. Toma [a,b,c,d]como argumento. Devuelve una matriz booleana de bits. *

⌈/=⌽

Pruébalo en línea!

⌈/ ¿El máximo del argumento

= igual (vectorises)

 ¿El reverso del argumento?

* Tenga en cuenta que APL almacena matrices de booleanos usando un bit por valor, por lo que esto realmente devuelve una palabra de 4 bits, a pesar de la forma de visualización 0 0 1 0.



2

Perl 6 , 12 bytes

{$_ X==.max}

Pruébalo en línea!

Bloque de código anónimo que toma una lista de enteros y devuelve una lista de booleanos. Si necesitamos regresar como un número, son +4 bytes para envolver el interior del bloque de código 2:[...].

Explicación:

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

OP ahora dice que no necesita envolver.
Adám

2

Japt, 5

m¶Urw

¡Intentalo!

-4 bytes gracias a @Oliver!
-2 bytes gracias a @Shaggy!

La entrada es una matriz de 4 elementos en el siguiente formato:

[d, c, b, a]

La salida es una matriz de bits.


Por supuesto que sí;) Aparentemente hay muchos atajos para aprender.
dana

Si una matriz booleana es una salida aceptable, puede ser de 7 bytes
Oliver

@Oliver, 5 bytes ;)
Shaggy

Ustedes son bastante buenos :) Eso es interesante cómo los rwconversos r("w")hacen una reducción al obtener repetidamente el máximo. Lo mismo con convertirse a U.m("===", ...). En cualquier caso, gracias por los consejos!
dana

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

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

(La última versión que convierte int32 en flotante no es perfectamente precisa para enteros grandes que se redondean al mismo flotante. Con la entrada flotante, el problema es el redondeador y esta función funciona correctamente si no hay NaN, identificando flotantes que se comparan == al máximo Las versiones enteras funcionan para todas las entradas, tratándolas como complemento de 2 firmado).

Todo esto funciona en modo 16/32/64 bits con el mismo código de máquina.

Una convención de llamadas de stack-args haría posible recorrer los args dos veces (encontrar max y luego comparar), posiblemente dándonos una implementación más pequeña, pero no he probado ese enfoque.

x86 SIMD tiene un mapa de bits vector-> entero como una sola instrucción ( pmovmskbo movmskpspd), por lo que era natural para esto a pesar de que las instrucciones MMX / SSE tienen al menos 3 bytes de longitud. Las instrucciones SSSE3 y posteriores son más largas que SSE2, y las instrucciones MMX / SSE1 son las más cortas. Se pmax*introdujeron diferentes versiones de (max. Entero vertical empaquetado) en diferentes momentos, con SSE1 (para mmx regs) y SSE2 (para xmm regs) solo con palabra firmada (16 bits) y byte sin firmar.

( pshufwy pmaxswen los registros MMX son nuevos con Katmai Pentium III, por lo que realmente requieren SSE1, no solo el bit de la función MMX CPU).

Esto se puede llamar desde C como unsigned max4_mmx(__m64)con el i386 System V ABI, que pasa un __m64argumento en mm0. (No x86-64 System V, que pasa __m64en 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

Si hubiera un pmovmskw, lo que habría guardado el packsswby el and(3 + 2 bytes). No necesitamos and eax, 0x0fporque pmovmskben un registro MMX ya ceramos los bytes superiores. Los registros MMX tienen solo 8 bytes de ancho, por lo que AL de 8 bits cubre todos los posibles bits distintos de cero.

Si supiéramos que nuestras entradas no son negativas, podríamospacksswb mm1, mm0 producir bytes con signo no negativo en los 4 bytes superiores de mm1, evitando la necesidad de anddespués pmovmskb. Así 24 bytes.

El paquete x86 con saturación con signo trata la entrada y la salida como con signo, por lo que siempre conserva el bit de signo. ( https://www.felixcloutier.com/x86/packsswb:packssdw ). Dato curioso: el paquete x86 con saturación sin signo todavía trata la entrada como firmada. Esta podría ser la razón PACKUSDWpor la que no se introdujo hasta SSE4.1, mientras que las otras 3 combinaciones de tamaño y firma existieron desde MMX / SSE2.


O con enteros de 32 bits en un registro XMM (y en pshufdlugar de pshufw), cada instrucción necesitaría un byte de prefijo más, excepto para movmskpsreemplazar el paquete / y. Pero pmaxsd/ pmaxudnecesita un byte extra extra ...

invocable desde C comounsigned max4_sse4(__m128i); con x86-64 System V, o MSVC vectorcall ( -Gv), ambos pasan __m128i/ __m128d/ __m128args en los registros XMM que comienzan con 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

O si aceptamos la entrada como float, podemos usar las instrucciones SSE1. El floatformato puede representar una amplia gama de valores enteros ...

O si cree que eso está doblando las reglas demasiado, comience con un byte 0F 5B C0 cvtdq2ps xmm0, xmm0para convertir, haciendo una función de 27 bytes que funcione para todos los enteros que son exactamente representables como IEEE binary32 float, y muchas combinaciones de entradas donde algunas de las entradas obtienen redondeado a un múltiplo de 2, 4, 8 o lo que sea durante la conversión. (Por lo tanto, es 1 byte más pequeño que la versión SSE4.1 y funciona en cualquier x86-64 con solo SSE2).

Si alguna de las entradas flotantes es NaN, tenga en cuenta que maxps a,bse implementa exactamente (a<b) ? a : b, manteniendo el elemento del segundo operando en desordenado . Por lo tanto, es posible que esto regrese con un mapa de bits distinto de cero, incluso si la entrada contiene algo de NaN, dependiendo de dónde se encuentren.

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 y mezclar con pshufdsigue siendo nuestra mejor apuesta: shufps dst,src,imm8lee la entrada para la mitad baja dst de dst . Y necesitamos un copy-and-shuffle no destructivo las dos veces, por lo que 3-byte movhlpsy unpckhps/ pd están fuera. Si estuviéramos reduciendo a un máximo escalar, podríamos usarlos, pero cuesta emitir otra instrucción antes de comparar si no tenemos el máximo en todos los elementos.


Relacionado: SSE4.1 phminposuwpuede encontrar la posición y el valor del mínimo uint16_ten un registro XMM. No creo que sea una ganancia restar 65535 para usarlo como máximo, pero veo una respuesta SO sobre cómo usarlo para un máximo de bytes o enteros con signo.


1

Python 3.8 (prelanzamiento) , 67 bytes

Función Lambda que toma 4 enteros, el bit cambia el resultado booleano de su comparación al valor máximo con la ayuda del nuevo operador de asignación de Python 3.8 , y devuelve el OR bit a bit de los resultados

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

Pruébalo en línea!


: = me recuerda los viejos tiempos donde ese era el operador de asignación con la fórmula de Lotus Notes. Supongo que tendré que echar un vistazo a 3.8 por los viejos tiempos :)
ElPedro



1

JavaScript (ES6), 30 bytes

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

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

Pruébalo en línea!


1
OP ha aclarado que de hecho puede devolver 4 valores booleanos.
Adám


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]

Pruébalo en línea!

Toma entrada como [a,b,c,d]y genera una lista de booleanos.

Editado para que sea una función adecuada, luego guardó 2 bytes eliminando los corchetes alrededor del condicional.


1
Hola y bienvenidos a PPCG. Tal como está, su respuesta tiene la forma de un fragmento, que no está permitido. Corrija su respuesta para cumplir con nuestro consenso de E / S , es decir, que sea una función o un programa completo.
Jonathan Frech

1
Editado Primera vez Agradezco la cabeza!
Bsoned

Puede reducirlo a 37 bytes utilizando esta comprensión de la lista dentro de una lambda. ¡Bienvenido a PPCG y disfrute de su estadía!
Value Ink el

@ValueInk Eliminar el espacio en blanco superfluo ahorra otro byte.
Jonathan Frech

1

1. Python 3.5, 90 bytes

Toma secuencia de números como parámetros. Devuelve una cadena "binaria"

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

ejemplo:

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

Explicación

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 interactivo de Visual C #) , 26 bytes

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

Pruébalo en línea!

Toma entrada en formato [d,c,b,a]. Todos los demás a continuación toman entrada como[a,b,c,d]

C # (compilador interactivo de Visual C #) , 35 bytes

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

Devuelve un IEnumerable<bool>.

Pruébalo en línea!

C # (compilador interactivo de Visual C #) , 39 bytes

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

Devuelve un IEnumerable<int>, que representa bits.

Pruébalo en línea!

C # (compilador interactivo de Visual C #) , 49 bytes

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

Imprime una cadena binaria en STDOUT.

Pruébalo en línea!


IEnumerable<bool> es aceptable
Adám

0

PHP, 54 bytes

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

o

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

tomar datos de los argumentos de la línea de comandos. Corre con ellos-nr o pruébalos en línea .


0

Aquí hay una versión JS que sale como binaria

actualización: más corta con join, y sin la búsqueda:

JavaScript (Node.js) , 42 bytes

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

Pruébalo en línea!

Anterior, con búsqueda, 49 bytes

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

Pruébalo en línea!

Anterior, con reducción, 52 bytes:

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

Pruébalo en línea!

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][...]01

@Arnauld parece obvio ahora. ¡Gracias!
Pureferret

0

C # (compilador interactivo de Visual C #) , 51 bytes

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

Pruébalo en línea!

Arriba hay una función anónima que se genera modificando un argumento . La salida es una matriz de 1 y 0.

A continuación se muestra una función recursiva que genera un número entero.

C # (compilador interactivo de 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);

Pruébalo en línea!

Ambas funciones toman la entrada como una matriz de 4 elementos.

[d, c, b, a]

No necesita generar un número entero.
Adám

@ Adam - gracias :) Me di cuenta de esto después de publicar mientras estaba trabajando en mi otra respuesta. Antes de tener la oportunidad de cambiar, había otra respuesta de C # que usaba muchos de los buenos trucos.
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)

Toma argumentos como parámetros de línea de comandos en orden inverso. Funciona calculando aritméticamente el máximo de los parámetros reduciéndolos y agregando solo diferencias positivas del máximo en ejecución, luego mapeando cada parámetro nuevamente esta vez comparándolo con el máximo. Convenientemente cmd/cset/ano genera una nueva línea, por lo que los resultados se concatenan automáticamente. El %f%simplemente ahorra 5 bytes en lo que sería una construcción repetida.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.